英文:
appending to a slice in for loop with unexpected results
问题
这可能是一个愚蠢的问题,但是当我尝试将一个[]byte切片追加到一个[][]byte
切片时,我得到了奇怪的结果。
这是我的代码:
func Normalizer(s string) (ss [][]byte) {
ss = make([][]byte, 0)
// norm
var ia norm.Iter
ia.InitString(norm.NFC, s)
for !ia.Done() {
next := ia.Next()
fmt.Println(next)
// [226 128 139]
// [227 128 129]
// [39]
// [226 128 153]
// [46]
// [44]
// [63]
// [33]
// [92]
// [10]
// [226 128 153]
// ...
ss = append(ss, next)
}
ia.Done()
fmt.Println(ss)
return
}
我期望得到这样的结果:
// [[226 128 139] [227 128 129] [39] [226 128 153] [46] [44] [63] [33] [92] [10] [226 128 153]...]
但是实际上我得到了这样的结果:
// [[226 129 128] [226 129 128] [226] [226 129 128] [226] [226] [226] [226] [226] [226] [226 129 128]...]
我不知道为什么会这样。希望能得到帮助和解释。
英文:
It could be a silly question but when I try to append a []byte slice to a [][]byte
slice I get weird results.
Here is my code:
func Normalizer(s string) (ss [][]byte) {
ss = make([][]byte, 0)
// norm
var ia norm.Iter
ia.InitString(norm.NFC, s)
for !ia.Done() {
next := ia.Next()
fmt.Println(next)
// [226 128 139]
// [227 128 129]
// [39]
// [226 128 153]
// [46]
// [44]
// [63]
// [33]
// [92]
// [10]
// [226 128 153]
// ...
ss = append(ss, next)
}
ia.Done()
fmt.Println(ss)
return
}
I'm expecting somethin like this:
// [[226 128 139] [227 128 129] [39] [226 128 153] [46] [44] [63] [33] [92] [10] [226 128 153]...]
but instead i get this:
// [[226 129 128] [226 129 128] [226] [226 129 128] [226] [226] [226] [226] [226] [226] [226 129 128]...]
and I have no idea why. Help and explanation would be appreciated.
答案1
得分: 3
切片是一个结构体,包含指向底层数组的指针、长度和容量。
type slice struct {
array unsafe.Pointer
len int
cap int
}
在追加切片结构之后,你正在更改底层数组。ia.Next()
重用其返回缓冲区。
例如,
package main
import (
"fmt"
"golang.org/x/text/unicode/norm"
)
func Normalizer(s string) (ss [][]byte) {
ss = make([][]byte, 0)
var ia norm.Iter
ia.InitString(norm.NFC, s)
for !ia.Done() {
next := ia.Next()
fmt.Println(string(next), &next[0])
ss = append(ss, next)
}
fmt.Println()
for i := range ss {
fmt.Println(string(ss[i]), &ss[i][0])
}
fmt.Println()
return
}
func main() {
ss := Normalizer("abc")
fmt.Printf("%s\n", ss)
}
输出:
a 0xc420092228
b 0xc420092228
c 0xc420092228
c 0xc420092228
c 0xc420092228
c 0xc420092228
[c c c]
将切片结构的副本替换为具有新底层数组的新切片结构:
next := append([]byte(nil), ia.Next()...)
例如,
package main
import (
"fmt"
"golang.org/x/text/unicode/norm"
)
func Normalizer(s string) (ss [][]byte) {
ss = make([][]byte, 0)
var ia norm.Iter
ia.InitString(norm.NFC, s)
for !ia.Done() {
next := append([]byte(nil), ia.Next()...)
fmt.Println(string(next), &next[0])
ss = append(ss, next)
}
fmt.Println()
for i := range ss {
fmt.Println(string(ss[i]), &ss[i][0])
}
fmt.Println()
return
}
func main() {
ss := Normalizer("abc")
fmt.Printf("%s\n", ss)
}
输出:
a 0xc4200120d0
b 0xc4200120e8
c 0xc420012108
a 0xc4200120d0
b 0xc4200120e8
c 0xc420012108
[a b c]
参考资料:
Go Slices: usage and internals
Arrays, slices (and strings): The mechanics of 'append'
英文:
A slice is a struct with a pointer to an underlying array, a length, and a capacity.
type slice struct {
array unsafe.Pointer
len int
cap int
}
You are changing the underlying array after you have appended the slice struct. ia.Next()
reuses its return buffer.
For example,
package main
import (
"fmt"
"golang.org/x/text/unicode/norm"
)
func Normalizer(s string) (ss [][]byte) {
ss = make([][]byte, 0)
var ia norm.Iter
ia.InitString(norm.NFC, s)
for !ia.Done() {
next := ia.Next()
fmt.Println(string(next), &next[0])
ss = append(ss, next)
}
fmt.Println()
for i := range ss {
fmt.Println(string(ss[i]), &ss[i][0])
}
fmt.Println()
return
}
func main() {
ss := Normalizer("abc")
fmt.Printf("%s\n", ss)
}
Output:
a 0xc420092228
b 0xc420092228
c 0xc420092228
c 0xc420092228
c 0xc420092228
c 0xc420092228
[c c c]
Replace a copy of a slice struct
next := ia.Next()
with a new slice struct with a new underlying array
next := append([]byte(nil), ia.Next()...)
For example,
package main
import (
"fmt"
"golang.org/x/text/unicode/norm"
)
func Normalizer(s string) (ss [][]byte) {
ss = make([][]byte, 0)
var ia norm.Iter
ia.InitString(norm.NFC, s)
for !ia.Done() {
next := append([]byte(nil), ia.Next()...)
fmt.Println(string(next), &next[0])
ss = append(ss, next)
}
fmt.Println()
for i := range ss {
fmt.Println(string(ss[i]), &ss[i][0])
}
fmt.Println()
return
}
func main() {
ss := Normalizer("abc")
fmt.Printf("%s\n", ss)
}
Output:
a 0xc4200120d0
b 0xc4200120e8
c 0xc420012108
a 0xc4200120d0
b 0xc4200120e8
c 0xc420012108
[a b c]
References:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论