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.
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
", 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
", ss)
}
Output:
a 0xc4200120d0
b 0xc4200120e8
c 0xc420012108
a 0xc4200120d0
b 0xc4200120e8
c 0xc420012108
[a b c]
References: