握月担风
  • 标签🏷️
主页 » 🧩 标签

String

转换bytes和string的最佳实践

本文golang源码为1.18版本 标准转换 使用标准转换是最常见的选择 package main func main() { s := "Hello, world!" // string转byte数组 b := []byte(s) // byte数组转string s2 := string(b) } 该转换语句会被go编译器翻译为runtime层的方法调用,其中[]byte到string的转换对应/src/runtime/string.go:81处的slicebytetostring函数;而string到[]byte的转换对应的则是/src/runtime/string.go:172处的stringtoslicebyte函数。 先来看看比较简单的stringtoslicebyte函数,tmpBuf类型是个大小为32的byte数组。 // The constant is known to the compiler. // There is no fundamental theory behind this number. 🤣 const tmpStringBufSize = 32 type tmpBuf [tmpStringBufSize]byte func stringtoslicebyte(buf *tmpBuf, s string) []byte { var b []byte if buf != nil && len(s) <= len(buf) { *buf = tmpBuf{} b = buf[:len(s)] } else { // 如果没有缓冲区或缓冲区大小不足,需要申请内存 b = rawbyteslice(len(s)) } // 复制数据 copy(b, s) return b } func rawbyteslice(size int) (b []byte) { // 容量计算,考虑内存对齐,寻找大小最匹配的内存块 cap := roundupsize(uintptr(size)) // 使用mallocgc申请对应大小的内存 p := mallocgc(cap, nil, false) // 如果要申请的size和最终计算得到的cap大小不一致,cap只会比size更大,清理掉多余的内存 if cap != uintptr(size) { memclrNoHeapPointers(add(p, uintptr(size)), cap-uintptr(size)) } // 将b指向这片申请好的内存。该slice不为空,故外部使用copy进行覆盖而不是append *(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)} return } 当需要转换的字符串长度小于32时,只会进行内存复制,而大于32的话,除了复制操作,还需要分配内存。 ...

2023-02-01 · 壹次心
© 2025 握月担风 Powered by Hugo & PaperMod