Created
May 14, 2020 21:22
-
-
Save bgadrian/a4f56313ef38b11efed6ea387818e8b9 to your computer and use it in GitHub Desktop.
go slices more tricks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// StringToImmutableBytes returns a slice of bytes from a string without allocating memory | |
// it is the caller's responsibility not to mutate the bytes returned. | |
func StringToImmutableBytes(s string) []byte { | |
if len(s) == 0 { | |
return nil | |
} | |
// NB(xichen): We need to declare a real byte slice so internally the compiler | |
// knows to use an unsafe.Pointer to keep track of the underlying memory so that | |
// once the slice's array pointer is updated with the pointer to the string's | |
// underlying bytes, the compiler won't prematurely GC the memory when the string | |
// goes out of scope. | |
var b []byte | |
byteHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b)) | |
// NB(xichen): This makes sure that even if GC relocates the string's underlying | |
// memory after this assignment, the corresponding unsafe.Pointer in the internal | |
// slice struct will be updated accordingly to reflect the memory relocation. | |
byteHeader.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data | |
// NB(xichen): It is important that we access s after we assign the Data | |
// pointer of the string header to the Data pointer of the slice header to | |
// make sure the string (and the underlying bytes backing the string) don't get | |
// GC'ed before the assignment happens. | |
l := len(s) | |
byteHeader.Len = l | |
byteHeader.Cap = l | |
return b | |
} | |
func concatSlices(slices ...[]byte) []byte { | |
var totalLen int | |
for _, s := range slices { | |
totalLen += len(s) | |
} | |
tmp := make([]byte, totalLen) | |
var i int | |
for _, s := range slices { | |
i += copy(tmp[i:], s) | |
} | |
return tmp | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment