Gobyte教程展示了如何在Golang中使用字节。
Go中的byte是一个无符号的8位整数。它的类型为uint8。byte的数值范围限制为0∼255。它可以表示一个ASCII字符。
Go使用类型为int32的rune来处理多字节字符。
bytes包实现了操作字节片的函数。它类似于strings包。
$ go version go version go1.18.1 linux/amd64
我们使用Go版本1.18。
Go字节示例
在下一个示例中,我们使用简单的字节。
package main
import "fmt"
func main() {
var a1 byte = 97
var a2 byte = 98
var a3 byte = 99
fmt.Println(a1)
fmt.Println(a2)
fmt.Println(a3)
fmt.Printf("%c\n", a1)
fmt.Printf("%c\n", a2)
fmt.Printf("%c\n", a3)
}
我们有三个字节。
var a1 byte = 97 var a2 byte = 98 var a3 byte = 99
字节是用byte数据类型定义的。
fmt.Printf("%c\n", a1)
fmt.Printf("%c\n", a2)
fmt.Printf("%c\n", a3)
使用%c格式动词,我们打印字节的字符表示。
$ go run first.go 97 98 99 a b c
我们必须显式地将一个变量设置为byte类型;否则,我们会得到不同的类型。
package main
import (
"fmt"
"reflect"
)
func main() {
var a byte = 97
var b = 98
c := 'c'
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println("-------------------------")
fmt.Printf("%c\n", a)
fmt.Printf("%c\n", b)
fmt.Printf("%c\n", c)
fmt.Println("-------------------------")
fmt.Println(reflect.TypeOf(a))
fmt.Println(reflect.TypeOf(b))
fmt.Println(reflect.TypeOf(c))
}
在代码示例中,我们有三个变量。
var a byte = 97
a变量具有byte数据类型。
var b = 98
因为我们没有显式设置数据类型,Go设置了一个默认的int类型。
c := 'c'
字符文字设置为rune类型(int32)。
$ go run types.go 97 98 99 ------------------------- a b c ------------------------- uint8 int int32
将字符串转为字节
在下面的示例中,我们将字符串转换为字节。
package main
import (
"fmt"
)
func main() {
fmt.Println([]byte("falcon"))
fmt.Println([]byte("ÄereÅ¡Åa"))
}
我们使用[]byte()类型转换将两个字符串转换为字节。
$ go run str2bytes.go [102 97 108 99 111 110] [196 141 101 114 101 197 161 197 136 97]
将字节转为字符串
在下面的示例中,我们将字节转换为字符串。
package main
import "fmt"
func main() {
data := []byte{102, 97, 108, 99, 111, 110}
fmt.Println(data)
fmt.Println(string(data))
}
我们使用string函数将一段字节转换为字符串。
$ go run bytes2str.go [102 97 108 99 111 110] falcon
去计算字节数
我们使用len函数计算字节数。为了计算符文,我们使用utf8.RuneCountInString函数。
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
msg := "one ð"
n1 := len(msg)
n2 := utf8.RuneCountInString(msg)
fmt.Println(n1)
fmt.Println(n2)
}
我们计算msg字符串的字节数和符文数。
$ go run counting.go 8 5
有五个符文和八个字符。这意味着我们有一个包含四个字节的符文。
去字节读取文件
Go中的许多内置I/O函数返回一段字节。
falcon sky cup oak water
我们阅读了这个文本文件。
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
content, err := ioutil.ReadFile("words.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(content)
fmt.Println("-------------")
fmt.Println(string(content))
}
ioutil.ReadFile读取指定文件并将其内容作为字节片返回。
$ go run read_file.go [102 97 108 99 111 110 10 115 107 121 10 99 117 112 10 111 97 107 10 119 97 116 101 114] ------------- falcon sky cup oak water
去字节读取二进制文件
在下面的例子中,我们读取一个二进制文件并以十六进制的形式输出它。
package main
import (
"bufio"
"encoding/hex"
"fmt"
"io"
"log"
"os"
)
func main() {
f, err := os.Open("favicon.ico")
if err != nil {
log.Fatal(err)
}
defer f.Close()
reader := bufio.NewReader(f)
buf := make([]byte, 256)
for {
_, err := reader.Read(buf)
if err != nil {
if err != io.EOF {
fmt.Println(err)
}
break
}
fmt.Printf("%s", hex.Dump(buf))
}
}
hex.Dump函数返回一个字符串,其中包含给定数据的十六进制转储。十六进制转储的格式与hexdump-CUnix命令的输出相匹配。
$ go run read_binary.go 00000000 00 00 01 00 01 00 10 10 00 00 00 00 00 00 68 05 |..............h.| 00000010 00 00 16 00 00 00 28 00 00 00 10 00 00 00 20 00 |......(....... .| 00000020 00 00 01 00 08 00 00 00 00 00 00 01 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 |................| 00000040 00 00 ff ff ff 00 4d 45 3d 00 00 00 00 00 00 00 |......ME=.......| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| ...
转义字节
任意字符值可以使用反斜杠转义进行编码,并使用字符串或符文文字。Go支持一种通用格式,其中一个字节表示为\x后跟两个十六进制值。
package main
import (
"fmt"
)
func main() {
fmt.Println("\xF0\x9F\x92\xBF")
fmt.Println("\xF0\x9F\x8E\xB2")
fmt.Println("\xF0\x9F\x90\xA8")
fmt.Println("\xF0\x9F\x90\xA7")
fmt.Println("\xF0\x9F\x90\xAB")
fmt.Println("\xF0\x9F\x90\xAC")
}
在代码示例中,我们打印了六个表情符号字符。这些表情符号被指定为转义字节。
$ go run escaped_bytes.go ð¿ ð² ð¨ ð§ ð« ð¬
Go字节函数
bytes包包含用于操作字节片的函数。
package main
import (
"bytes"
"fmt"
)
func main() {
data1 := []byte{102, 97, 108, 99, 111, 110} // falcon
data2 := []byte{111, 110} // on
if bytes.Contains(data1, data2) {
fmt.Println("contains")
} else {
fmt.Println("does not contain")
}
if bytes.Equal([]byte("falcon"), []byte("owl")) {
fmt.Println("equal")
} else {
fmt.Println("not equal")
}
data3 := []byte{111, 119, 108, 9, 99, 97, 116, 32, 32, 32, 32, 100, 111,
103, 32, 112, 105, 103, 32, 32, 32, 32, 98, 101, 97, 114}
fields := bytes.Fields(data3)
fmt.Println(fields)
for _, e := range fields {
fmt.Printf("%s ", string(e))
}
fmt.Println()
}
在代码示例中,我们使用了Contains、Equal和Fields函数。
if bytes.Contains(data1, data2) {
fmt.Println("contains")
} else {
fmt.Println("does not contain")
}
使用Contains,我们检查data2切片是否是data1的子切片。
if bytes.Equal([]byte("falcon"), []byte("owl")) {
fmt.Println("equal")
} else {
fmt.Println("not equal")
}
使用Equal,我们检查两个切片是否具有相同的长度并包含相同的字节。
fields := bytes.Fields(data3)
Fields函数将字节切片拆分为子切片,删除任意空格字符,包括换行符。
$ go run byte_funs.go contains not equal [[111 119 108] [99 97 116] [100 111 103] [112 105 103] [98 101 97 114]] owl cat dog pig bear
在下一个例子中,我们使用另外三个函数。
package main
import (
"bytes"
"fmt"
)
func main() {
data := [][]byte{[]byte("an"), []byte("old"), []byte("wolf")}
joined := bytes.Join(data, []byte(" "))
fmt.Println(data)
fmt.Println(joined)
fmt.Println(string(joined))
fmt.Println("--------------------------")
data2 := []byte{102, 97, 108, 99, 111, 110, 32}
data3 := bytes.Repeat(data2, 3)
fmt.Println(data3)
fmt.Println(string(data3))
fmt.Println("--------------------------")
data4 := []byte{32, 32, 102, 97, 108, 99, 111, 110, 32, 32, 32}
data5 := bytes.Trim(data4, " ")
fmt.Println(data5)
fmt.Println(string(data5))
}
该示例使用Join连接字节切片,使用Repeat重复字节切片,并使用Trim修剪指定字节的字节切片。
$ go run byte_funs2.go [[97 110] [111 108 100] [119 111 108 102]] [97 110 32 111 108 100 32 119 111 108 102] an old wolf -------------------------- [102 97 108 99 111 110 32 102 97 108 99 111 110 32 102 97 108 99 111 110 32] falcon falcon falcon -------------------------- [102 97 108 99 111 110] falcon
转到bytes.Buffer
bytes.Buffer是一个可变大小的字节缓冲区,具有Read和Write方法。
package main
import (
"bytes"
"fmt"
)
func main() {
var buf bytes.Buffer
buf.Write([]byte("a old"))
buf.WriteByte(32)
buf.WriteString("cactus")
buf.WriteByte(32)
buf.WriteByte(32)
buf.WriteRune('ðµ')
fmt.Println(buf)
fmt.Println(buf.String())
}
我们用Write、WriteByte、WriteString、WriteByte构建一个bytes.Buffercode>和WriteRune方法。
$ go run buffer.go
{[97 32 111 108 100 32 99 97 99 116 117 115 32 32 240 159 140 181] 0 0}
a old cactus ðµ
在本教程中,我们使用了Golang中的字节。
列出所有Go教程。
