Skip to content

Instantly share code, notes, and snippets.

@skyitachi
Created February 21, 2021 01:29
Show Gist options
  • Save skyitachi/f8f22a390f547466216b0a4084b98bee to your computer and use it in GitHub Desktop.
Save skyitachi/f8f22a390f547466216b0a4084b98bee to your computer and use it in GitHub Desktop.
slice_convert
package main
import (
"fmt"
"reflect"
"testing"
"unicode/utf8"
"unsafe"
)
func TestStringToByte(t *testing.T) {
s := "0123"
// s[0] = '1'
fmt.Println(s)
s = "你好世界"
n := 0
for _, c := range s {
n++
fmt.Print(c)
}
fmt.Println("count: ", n)
}
func genString(sLen int) string {
var s string
for i := 0; i < sLen; i++ {
s += fmt.Sprintf("%d", i%10)
}
return s
}
func genSliceByte(sLen int) []byte {
return []byte(genString(sLen))
}
func genSliceRune(sLen int) []rune {
ret := make([]rune, sLen, sLen)
for i := 0; i < sLen; i++ {
ret[i] = '你'
}
return ret
}
func BenchmarkStringToByteSlice(b *testing.B) {
s := genString(10000)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
bs := []byte(s)
if len(bs) != len(s) {
b.Error("error")
}
}
}
func BenchmarkStringToByteSliceUnsafe(b *testing.B) {
s := genString(10000)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
strHeader := *(*reflect.StringHeader)(unsafe.Pointer(&s))
bs := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: strHeader.Data,
Len: strHeader.Len,
Cap: strHeader.Len,
}))
if len(bs) != len(s) {
b.Error("error")
}
}
}
func BenchmarkSliceByteToString(b *testing.B) {
bs := genSliceByte(100)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s := string(bs)
if len(s) != len(bs) {
b.Error("error")
}
}
}
func BenchmarkSliceByteToStringUnsafe(b *testing.B) {
bs := genSliceByte(100)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s := *(*string)(unsafe.Pointer(&bs))
if len(s) != len(bs) {
b.Log("slice: ", len(bs), " string: ", len(s))
b.Error("error: ")
}
}
}
func BenchmarkSliceRuneToString(b *testing.B) {
bs := genSliceRune(100)
s1 := string(bs)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s := string(bs)
if len(s1) != len(s) {
b.Error("error")
}
}
}
func BenchmarkSliceRuneToStringUnsafe(b *testing.B) {
bs := genSliceRune(100)
s1 := string(bs)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
var l int
for _, r := range bs {
l += utf8.RuneLen(r)
}
s := *(*string)(unsafe.Pointer(&reflect.StringHeader{
Data: (*(*reflect.SliceHeader)(unsafe.Pointer(&bs))).Data,
Len: l,
}))
if len(s1) != len(s) {
b.Error("error")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment