字节.字符串() vs 字节.Bytes() in Go 中



考虑这样的文本文件:

Some text
here.
---
More text
another line.
---
Third part of text.

我想把它分成三部分,用---分隔符分开。这些部分应存储在地图中。

现在,具有不同类型的完全相同的程序。

当我使用string时,一切正常:

KEY: 0
Some text
here.
KEY: 1
More text
another line.
KEY: 2
Third part of text.

https://play.golang.org/p/IcGdoUNcTEe

当我使用[]byte时,事情变得一团糟:

KEY: 0
Third part of teKEY: 1
Third part of text.
ne.
KEY: 2
Third part of text.

https://play.golang.org/p/jqLhCrqsvOs

为什么?


计划1 (string(:

func main() {
parts := parseParts([]byte(input))
for k, v := range parts {
fmt.Printf("KEY: %dn%s", k, v)
}
}
func parseParts(input []byte) map[int]string {
parts := map[int]string{}
s := bufio.NewScanner(bytes.NewReader(input))
buf := bytes.Buffer{}
i := 0
for s.Scan() {
if s.Text() == "---" {
parts[i] = buf.String()
buf.Reset()
i++
continue
}
buf.Write(s.Bytes())
buf.WriteString("n")
}
parts[i] = buf.String()
return parts
}

计划2 ([]byte(:

func main() {
parts := parseParts([]byte(input))
for k, v := range parts {
fmt.Printf("KEY: %dn%s", k, v)
}
}
func parseParts(input []byte) map[int]string {
parts := map[int]string{}
s := bufio.NewScanner(bytes.NewReader(input))
buf := bytes.Buffer{}
i := 0
for s.Scan() {
if s.Text() == "---" {
parts[i] = buf.String()
buf.Reset()
i++
continue
}
buf.Write(s.Bytes())
buf.WriteString("n")
}
parts[i] = buf.String()
return parts
}

在字符串版本中,

parts[i] = buf.String()

每次将parts[i]设置为新字符串。 在[]byte版本中,

parts[i] = buf.Bytes()

每次将parts[i]设置为由同一数组支持的字节片。 所有三个切片的后备数组内容都相同,但长度与创建时的长度匹配,这就是为什么所有三个切片都显示相同的内容但在不同位置被切断的原因。

您可以替换字节切片行

parts[i] = buf.Bytes()

像这样:

bb := buf.Bytes()
b := make([]byte, len(bb))
copy(b, bb)
parts[i] = b

为了使行为与字符串版本匹配。 但是字符串版本更容易,更符合您似乎要做的事情。

不同之处在于bytes.Buffer.String复制内存,而bytes.Buffer.Bytes则不复制内存。 引用文档,

该片仅在下一次缓冲区修改之前有效(即,仅在下一次调用读取、写入、重置或截断等方法之前(。

最新更新