在 Go 1.19 的开发中, string.SliceHeader和string.StringHeader经历了一个生死存亡的争斗,这两个类型一度被标记为弃用(deprecated),但是这两个类型经常用在 slice of byte 和 string 高效互转的场景中,如果被标记为弃用,但是目前还没有可替代的方法,所以这两个类型又把弃用标记去掉了,如无意外,它们也会在 Go 1.20 再次被标记为弃用。
var L = 1024 * 1024 var str = strings.Repeat("a", L) var s = bytes.Repeat([]byte{'a'}, L)
var str2 string var s2 []byte
funcBenchmarkString2Slice(b *testing.B) { for i := 0; i < b.N; i++ { bt := []byte(str) iflen(bt) != L { b.Fatal() } } }
funcBenchmarkString2SliceReflect(b *testing.B) { for i := 0; i < b.N; i++ { bt := *(*[]byte)(unsafe.Pointer(&str)) iflen(bt) != L { b.Fatal() } } }
funcBenchmarkString2SliceUnsafe(b *testing.B) { for i := 0; i < b.N; i++ { bt := unsafe.Slice(unsafe.StringData(str), len(str)) iflen(bt) != L { b.Fatal() } } }
funcBenchmarkSlice2String(b *testing.B) { for i := 0; i < b.N; i++ { ss := string(s) iflen(ss) != L { b.Fatal() } } }
funcBenchmarkSlice2StringReflect(b *testing.B) { for i := 0; i < b.N; i++ { ss := *(*string)(unsafe.Pointer(&s)) iflen(ss) != L { b.Fatal() } } }
funcBenchmarkSlice2StringUnsafe(b *testing.B) { for i := 0; i < b.N; i++ { ss := unsafe.String(unsafe.SliceData(s), len(str)) iflen(ss) != L { b.Fatal() } } }