Go 语言类型 字节型

基本概念

字节类型用于表示单个数据字节,本质上是 uint8 类型别名,在内存中长度为 1 字节。单个字节可以用来存储一个标准 ASCII 字符,更常用于处理和表示二进制数据。

声明和初始化

初始化时,可以将字符或不大于 255 的正整数赋值给字节型变量:

package main

import "fmt"

func main() {
	// 默认零值为 0
	var a byte

	// 声明为字节类型,赋值字符
	var b byte = 'b'

	// 短变量声明,使用数字字面值(ASCII 码值)
	c := byte(99)

	fmt.Printf("字符值: %c,ASCII 码值:%v\n", a, a) // 输出字符   和 ASCII 码值 0
	fmt.Printf("字符值: %c,ASCII 码值:%v\n", b, b) // 输出字符 b 和 ASCII 码值 98
	fmt.Printf("字符值: %c,ASCII 码值:%v\n", c, c) // 输出字符 c 和 ASCII 码值 99
}

字节型切片

字节型切片几乎用于所有读写接口中,可以直接使用字节字面值数组初始化字节切片,也可以将字符串转换为字节切片:

package main

import "fmt"

func main() {
	// 字节型切片转字符串
	byteSlice1 := []byte{72, 101, 108, 108, 111} // 直接使用字节值
	fmt.Println(string(byteSlice1))              // 输出: "Hello"

	// 字符串转字节型切片
	byteSlice2 := []byte("World")
	fmt.Println(byteSlice2) // 输出: [87 111 114 108 100]
}

在标准库 bytes 包中,提供一系列方法和函数,用于操作和处理字节切片。下面是个简单演示:

package main

import (
	"bytes"
	"fmt"
)

func main() {
	a := []byte("hello, world! ")
	b := []byte("golang")

	// 比较操作,结果为布尔值
	fmt.Println(bytes.Equal(a, b)) // 输出:false

	// 修剪操作,修剪切片首尾中感叹号
	fmt.Println(string(bytes.Trim(a, "!"))) // 输出:hello, world

	// 分割操作,以逗号作为分割符,最多分割 2 次
	c := bytes.SplitN(a, []byte(", "), 2)
	fmt.Println(c) // 输出:[[104 101 108 108 111] [119 111 114 108 100 33]]

	// 连接操作,将两个切片用 - 拼接起来
	fmt.Println(string(bytes.Join(c, []byte(" - ")))) // 输出:hello - world!

	// 搜索操作,搜索指定内容位置或搜索是否包含指定内容
	fmt.Println(bytes.Index(a, []byte("world")))    // 输出:7
	fmt.Println(bytes.LastIndex(a, []byte("o")))    // 输出:8
	fmt.Println(bytes.Contains(a, []byte("world"))) // 输出:true

	// 替换操作,将 world 替换为 golang,不限替换次数
	fmt.Println(string(bytes.Replace(a, []byte("world"), b, -1))) // 输出:hello, golang!

	// 写入缓冲区,支持字节切片
	var buffer bytes.Buffer
	buffer.Write(a)
	buffer.Write(b)
	fmt.Println(buffer.String()) // 输出:hello, world!golang
}

大多数 bytes 包中功能和用法同 strings 包相似。

使用场景

字节类型常用于文件读写、网络编程和数据加密等操作中。

文件读写

文件通常以二进制格式存储和读取,所以字节类型在文件读写操作中被广泛使用:

package main

import (
	"fmt"
	"os"
)

func main() {
	// 创建一个字节切片,并写入文件
	initialData := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
	os.WriteFile("example.bin", initialData, 0644)

	// 读取刚刚创建的二进制文件
	data, _ := os.ReadFile("example.bin")

	// 进行一些数据修改
	data[0] = 0x63
	data[1] = 0xFF

	// 打印文件内容
	fmt.Println(data) // 输出:[255 238 3 4 5]
	fmt.Println(string(data))
}

网络编程

在网络编程中,数据用字节流传输,使用字节切片可以直接操作这些字节:

package main

import (
	"fmt"
	"net"
)

func main() {
	// 建立连接
	conn, _ := net.Dial("tcp", "example.com:80")
	defer conn.Close()

	// 发送 HTTP GET 请求
	request := "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
	conn.Write([]byte(request))

	// 读取响应中前 256 个字节
	response := make([]byte, 256)
	n, _ := conn.Read(response)
	fmt.Println(string(response[:n]))
}

数据加密

数据加密也是直接操作字节,以减少内存使用:

package main

import (
    "crypto/sha256"
    "fmt"
)

func main() {
    data := "important data"
    hash := sha256.Sum256([]byte(data))
    fmt.Printf("SHA-256 Hash: %x\n", hash)
}