## 使用bytes和strings包 bytes 和 string 包有许多有用的函数以帮助使用者在字符串和字节类型之间进行处理和转换。这些函数可用于创建多种通用 I/O 接口的缓冲区。 ### 准备 请参阅上一节,关于使用常见I/O接口的准备步骤。 ### 实践 1. 创建buffer.go: ``` package bytestrings import ( "bytes" "io" "io/ioutil" ) // Buffer 演示了初始化字节缓冲区的一些技巧 // 实现了 io.Reader 接口 func Buffer(rawString string) *bytes.Buffer { // 将传入的字符串转换为字节数组 rawBytes := []byte(rawString) // 有很多方式使用字节数组或原始字符串建立缓冲区 var b = new(bytes.Buffer) b.Write(rawBytes) // 或者 b = bytes.NewBuffer(rawBytes) // 使用字符串建立字节数组 b = bytes.NewBufferString(rawString) return b } // ToString接收 io.Reader 并将其转换为字符串返回 func toString(r io.Reader) (string, error) { b, err := ioutil.ReadAll(r) if err != nil { return "", err } return string(b), nil } ``` 2. 建立bytes.go,[Golang学习 - bufio 包](https://www.cnblogs.com/golove/p/3282667.html)对buffio解读很完整,值得一读: ``` package bytestrings import ( "bufio" "bytes" "fmt" ) // WorkWithBuffer 会使用创建自 Buffer 函数的字节缓冲区 func WorkWithBuffer() error { rawString := "it's easy to encode unicode into a byte array ❤️" b := Buffer(rawString) // 使用b.Bytes()可以快速从字节缓冲区获取字节切片 // 使用b.String()可以快速从字节缓冲区获取字符串 fmt.Println(b.String()) // 由于*bytes.Buffer类型的b实现了io Reader 我们可以使用常见的reader函数 s, err := toString(b) if err != nil { return err } fmt.Println(s) // 可以创建一个 bytes reader 它实现了 // io.Reader, io.ReaderAt, // io.WriterTo, io.Seeker, io.ByteScanner, and io.RuneScanner // 接口 reader := bytes.NewReader([]byte(rawString)) // 我们可以使用其创建 scanner 以允许使用缓存读取和建立 token scanner := bufio.NewScanner(reader) scanner.Split(bufio.ScanWords) // 遍历所有的扫描token for scanner.Scan() { fmt.Print(scanner.Text()) } return nil } ``` 3. 建立 string.go: ``` package bytestrings import ( "fmt" "io" "os" "strings" ) // SearchString 展示了一系列在字符串中进行查询的方法 func SearchString() { s := "this is a test" // 返回 true 表明包含子串 fmt.Println(strings.Contains(s, "this")) // 返回 true 表明包含子串中的任何一字符a或b或c fmt.Println(strings.ContainsAny(s, "abc")) // 返回 true 表明以该子串开头 fmt.Println(strings.HasPrefix(s, "this")) // 返回 true 表明以该子串结尾 fmt.Println(strings.HasSuffix(s, "test")) } // ModifyString 展示了一系列修改字符串的方法 func ModifyString() { s := "simple string" // 输出 [simple string] fmt.Println(strings.Split(s, " ")) // 输出 "Simple String" fmt.Println(strings.Title(s)) // 输出 "simple string" 会移除头部和尾部的空白 s = " simple string " fmt.Println(strings.TrimSpace(s)) } // StringReader 演示了如何快速创建一个字符串的io.Reader接口 func StringReader() { s := "simple string\n" r := strings.NewReader(s) // 在标准输出上打印 s io.Copy(os.Stdout, r) } ``` 4. 建立main.go: ``` package main import "github.com/agtorre/go-cookbook/chapter1/bytestrings" func main() { err := bytestrings.WorkWithBuffer() if err != nil { panic(err) } // each of these print to stdout bytestrings.SearchString() bytestrings.ModifyString() bytestrings.StringReader() } ``` 5. 执行 go run main.go 6. 这会输出(*<small>原文此处将心形显示为乱码,不过在译者的win7 Go1.10.1环境下可以完整显示出来</small>*): ``` it's easy to encode unicode into a byte array ❤️ it's easy to encode unicode into a byte array ❤️ it'seasytoencodeunicodeintoabytearray❤️true true true true [simple string] Simple String simple string simple string ``` ### 说明 bytes 包在处理数据时提供了许多便利功能。 例如,使用流处理库或方法时,缓冲区比字节数组更灵活。一旦你创建了一个缓冲区,它可以用来满足io.Reader接口,所以你可以利用ioutil包中的各种函数来操作数据。 对于流应用,你可能需要使用buffer 和 scanner,bufio包可以在这些情况下派上用场。 有时,使用数组或切片更适合较小的数据集,或者当你的计算机上有大量内存,无需考虑过多考虑时。 Go为这些基本类型的接口之间的转换提供了很大的灵活性——在字符串和字节之间转换相对简单。使用字符串时,string包提供了许多方便的函数来搜索和处理字符串。在某些情况下,一个好的正则表达式可能是合适的,但大多数情况下,string和strconv包就足够了。string包允许你将字符串标题化,将其拆分为数组或修剪空白,它还提供了一个可以用来代替bytes包读取器类型的Reader接口。 * * * * 学识浅薄,错误在所难免。欢迎在群中就本书提出修改意见,以飨后来者,长风拜谢。 Golang中国(211938256) beego实战(258969317) Go实践(386056972)