SoFunction
Updated on 2025-03-04

Implement character slices and string rotation in go

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!