go / expert
Snippet
Zero-Copy String- und Byte-Konvertierungen via modernem unsafe Package API
Go 1.17 und 1.20 führten unsafe.Slice, unsafe.SliceData, unsafe.String und unsafe.StringData ein, um reflexionsbasiertes Hacking von StringHeader und SliceHeader zu ersetzen. Dies ermöglicht explizites, vom Compiler unterstütztes Zero-Copy-Casting zwischen unveränderlichen Strings und Byte-Slices für leistungskritische I/O-Pfade.
snippet.go
go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package mainimport ("fmt""unsafe")// BytesToString performs a zero-allocation conversion from []byte to string.// Safety: The underlying byte slice must not be mutated while the string is in use.func BytesToString(b []byte) string {if len(b) == 0 {return ""}return unsafe.String(unsafe.SliceData(b), len(b))}// StringToBytes performs a zero-allocation conversion from string to []byte.// Safety: The returned slice must NEVER be mutated, as strings in Go are immutable.func StringToBytes(s string) []byte {if len(s) == 0 {return nil}return unsafe.Slice(unsafe.StringData(s), len(s))}func main() {data := []byte("High-Performance Go")str := BytesToString(data)fmt.Printf("String: %s (len=%d)\n", str, len(str))strOrig := "Immutable Buffer"bytes := StringToBytes(strOrig)fmt.Printf("Bytes: %v (len=%d)\n", bytes, len(bytes))}
Erklärung
1
return unsafe.String(unsafe.SliceData(b), len(b))
Errechnet einen Zeiger auf das erste Element des Byte-Slices via unsafe.SliceData und erstellt eine String-Ansicht über den Speicher ohne Heap-Allokation.
2
return unsafe.Slice(unsafe.StringData(s), len(s))
Extrahiert den zugrundeliegenden schreibgeschützten Byte-Zeiger des Strings via unsafe.StringData und hüllt ihn ohne Speicherverdopplung in ein Byte-Slice ein.