Go 1.21
// Return a Slice, its underlying array starts from ptr, and its length and capacity are lenfunc Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType // Return a pointer to the underlying arrayfunc SliceData(slice []ArbitraryType) *ArbitraryType // Generate a string, the underlying array starts from ptr, and the length is len// returns a string value whose underlying bytes start at ptr and whose length is len // The len argument must be of integer type or an untyped constant // A constant len argument must be non-negative and representable by a value of type int // if it is an untyped constant it is given type int // At run time, if len is negative, or if ptr is nil and len is not zero, a run-time panic occurs // Since Go strings are immutable, the bytes passed to String must not be modified afterwards func String(ptr *byte, len IntegerType) string // Return the array at the bottom of the string// returns a pointer to the underlying bytes of str // For an empty string the return value is unspecified, and may be nil. // Since Go strings are immutable, the bytes returned by StringData must not be modified. func StringData(str string) *byte
Go 1.20
Deprecated two types of SliceHeader and StringHeader
Go 1.19
and efficient transition scenarios often used in slice of byte and string
// go1.18.3/src/reflect/ // SliceHeader is the runtime representation of a slice. // It cannot be used safely or portably and its representation may // change in a later release. // Moreover, the Data field is not sufficient to guarantee the data // it references will not be garbage collected, so programs must keep // a separate, correctly typed pointer to the underlying data. type SliceHeader struct { Data uintptr Len int Cap int } // StringHeader is the runtime representation of a string. // It cannot be used safely or portably and its representation may // change in a later release. // Moreover, the Data field is not sufficient to guarantee the data // it references will not be garbage collected, so programs must keep // a separate, correctly typed pointer to the underlying data. type StringHeader struct { Data uintptr Len int }
Slice has one more Cap field than String
Both data are stored in the Data array
Implementation method
Method 1
string(bytes) or []byte(str)
Poor performance
Method 2
// toBytes performs unholy acts to avoid allocations func toBytes(s string) []byte { return *(*[]byte)((&s)) } // toString performs unholy acts to avoid allocations func toString(b []byte) string { return *(*string)((&b)) }
Method 3
func SliceByteToString(b []byte) string { return *(*string)((&b)) } func StringToSliceByte(s string) []byte { x := (*[2]uintptr)((&s)) h := [3]uintptr{x[0], x[1], x[1]} return *(*[]byte)((&h)) }
Method 4
func Clone(s string) string { if len(s) == 0 { return "" } b := make([]byte, len(s)) copy(b, s) return *(*string)((&b)) }
Performance Testing
var L = 1024 * 1024 var str = ("a", L) var s = ([]byte{'a'}, L) var str2 string var s2 []byte func BenchmarkString2Slice(b *) { for i := 0; i < ; i++ { bt := []byte(str) if len(bt) != L { () } } } func BenchmarkString2SliceReflect(b *) { for i := 0; i < ; i++ { bt := *(*[]byte)((&str)) if len(bt) != L { () } } } func BenchmarkString2SliceUnsafe(b *) { for i := 0; i < ; i++ { bt := ((str), len(str)) if len(bt) != L { () } } } func BenchmarkSlice2String(b *) { for i := 0; i < ; i++ { ss := string(s) if len(ss) != L { () } } } func BenchmarkSlice2StringReflect(b *) { for i := 0; i < ; i++ { ss := *(*string)((&s)) if len(ss) != L { () } } } func BenchmarkSlice2StringUnsafe(b *) { for i := 0; i < ; i++ { ss := ((s), len(str)) if len(ss) != L { () } } }
Official production must be a good thing, so believe in GO1.21
This is the article about the implementation of character slices and string transfer in Go. For more related contents of character slices and string transfer, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!