首页
Preview

在 Go 1.20 中快速进行字符串到 []byte 和 []byte 到字符串的转换

Go语言在unsafe包中引入了一些函数,用于实现快速的string[]byte[]bytestring的转换。它非常快,详情请见https://www.sobyte.net/post/2022-09/string-byte-convertion/,但由于该解决方案使用内存指针而不是值拷贝,改变此类值会产生副作用。

快速string到[]byte转换

传统方式

通常的转换方式很简单,例如:

// string to []byte
bs := []byte("Hello")

// []byte to string
txt := string([]byte{72, 101, 108, 108, 111})

但是,值拷贝消耗更多资源(内存、CPU时间),这可能是关键的。

快速方式

Go 1.20在unsafe包中引入了新函数(SliceDataStringStringData),以提供完整的构造和解构切片和字符串值的能力,而不依赖于它们的确切表示方式,详情请见https://tip.golang.org/doc/go1.20

unsafe函数的使用示例可在https://go101.org/article/unsafe.html中找到:

import "unsafe"

func String2ByteSlice(str string) []byte {
 if str == "" {
  return nil
 }
 return unsafe.Slice(unsafe.StringData(str), len(str))
}

func ByteSlice2String(bs []byte) string {
 if len(bs) == 0 {
  return ""
 }
 return unsafe.String(unsafe.SliceData(bs), len(bs))
}

这些函数返回具有相同内存引用的另一种类型,因此比传统拷贝快得多。它有效,直到所引用的内存被改变。string是不可变的,但[]byte随时都可以被更改。让我们看看如果我们更改它会发生什么。

更改值

string到[]byte

在第一个示例中,返回的[]byte将被更改:

func TestString2ByteSlice(t *testing.T) {
 // given
 sampleStr1 := "012"
 // when
 sampleBytes1 := String2ByteSlice(sampleStr1)
 // then
 assert.Equal(t, []byte{0x30, 0x31, 0x32}, sampleBytes1)

 // when segfault!
 // sampleBytes1[1] = 0x39
}

sampleBytes1[1]会将'1'处的字节设置为'9',但会产生段错误,因为string类型是不可变的,Go会防止其更改:

unexpected fault address 0x5d523d
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x2 addr=0x5d523d pc=0x5878b4]

[]byte到string

在这个示例中,原始的字节切片将被更改:

func TestByteSlice2String(t *testing.T) {
 // given
 sampleBytes1 := []byte{0x30, 0x31, 0x32}
 // when
 sampleStr1 := ByteSlice2String(sampleBytes1)
 // then
 assert.Equal(t, "012", sampleStr1)

 // when
 sampleBytes1[1] = 0x39
 // then
 assert.Equal(t, "012", sampleStr1)
}

sampleBytes1[1]'1'处的字节设置为'9',这是成功的,返回的sampleStr1也将被更改:

--- FAIL: TestByteSlice2String (0.00s)
Error:       Not equal: 
             expected: "012"
             actual  : "092"

总结

新的转换方式很快,但是并非没有代价:如果更改了值,将会产生段错误或不想要的字符串更改。

译自:https://blog.devops.dev/fast-string-to-byte-and-byte-to-string-conversion-in-go-1-20-85bdb859ee67

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
菜鸟一只
你就是个黄焖鸡,又黄又闷又垃圾。

评论(0)

添加评论