Go中string与[]byte如何高效互转

您所在的位置:网站首页 byte数组转二维数组 Go中string与[]byte如何高效互转

Go中string与[]byte如何高效互转

2023-11-22 03:01| 来源: 网络整理| 查看: 265

前言

当我们使用go进行数据序列化或反序列化操作时,可能经常涉及到字符串和字节数组的转换。例如:

if str, err := json.Marshal(from); err != nil { panic(err) } else { return string(str) }

json序列化后为[]byte类型,需要将其转换为字符串类型。当数据量小时,类型间转换的开销可以忽略不计,但当数据量增大后,可能成为性能瓶颈,使用高效的转换方法能减少这方面的开销

数据结构

在了解其如何转换前,需要了解其底层数据结构

本文基于go 1.13.12

string:

type stringStruct struct { str unsafe.Pointer len int }

slice:

type slice struct { array unsafe.Pointer len int cap int }

与slice的结构相比,string缺少一个表示容量的cap字段,因此不能对string遍历使用内置的cap()函数

那为什么string不需要cap字段呢?因为go中string被设计为不可变类型(当然在很多其他语言中也是),

由于其不可像slice一样追加元素,也就不需要cap字段判断是否超出底层数组的容量,来决定是否扩容

只有len属性不影响for-range等读取操作,因为for-range操作只根据len决定是否跳出循环

那为什么字符串要设定为不可变呢?因为这样能保证字符串的底层数组不发生改变

举个例子,map中以string为键,如果底层字符数组改变,则计算出的哈希值也会发生变化,这样再从map中定位时就找不到之前的value,因此其不可变特性能避免这种情况发生,string也适合作为map的键。除此之外,不可变特性也能保障数据的线程安全

常规实现

字符串不可变有很多好处,为了维持其不可变特性,字符串和字节数组互转一般是通过数据拷贝的方式实现:

var a string = "hello world" var b []byte = []byte(a) // string转[]byte a = string(b) // []byte转string

这种方式实现简单,但是通过底层数据复制实现的,在编译期间分别转换成对slicebytetostring和stringtoslicebyte的函数调用

string转[]byte

func stringtoslicebyte(buf *tmpBuf, s string) []byte { var b []byte if buf != nil && len(s)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3