当前位置: 首页 > news >正文

go的字符切片和字符串互转

Go 1.21

// 返回一个Slice,它的底层数组自ptr开始,长度和容量都是len
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
// 返回一个指针,指向底层的数组
func SliceData(slice []ArbitraryType) *ArbitraryType
// 生成一个字符串,底层的数组开始自ptr,长度是len
// returns a string value whose underlying bytes start at ptr and whose length is len
// The len argument must be of integer type or an untyped constant
// A constant len argument must be non-negative and representable by a value of type int
// if it is an untyped constant it is given type int
// At run time, if len is negative, or if ptr is nil and len is not zero, a run-time panic occurs
// Since Go strings are immutable, the bytes passed to String must not be modified afterwards
func String(ptr *byte, len IntegerType) string
// 返回字符串底层的数组
// returns a pointer to the underlying bytes of str
// For an empty string the return value is unspecified, and may be nil.
// Since Go strings are immutable, the bytes returned by StringData must not be modified.
func StringData(str string) *byte

Go 1.20

废弃两个类型SliceHeader和StringHeader

Go 1.19

string.SliceHeader和string.StringHeader经常用在 slice of byte 和 string 高效互转场景

// go1.18.3/src/reflect/value.go
// SliceHeader is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may
// change in a later release.
// Moreover, the Data field is not sufficient to guarantee the data
// it references will not be garbage collected, so programs must keep
// a separate, correctly typed pointer to the underlying data.
type SliceHeader struct {                                                                                      Data uintptrLen  intCap  int
}// StringHeader is the runtime representation of a string.
// It cannot be used safely or portably and its representation may
// change in a later release.
// Moreover, the Data field is not sufficient to guarantee the data
// it references will not be garbage collected, so programs must keep
// a separate, correctly typed pointer to the underlying data.
type StringHeader struct {                                                                                     Data uintptrLen  int
}

Slice比String多一个Cap字段
两个的数据都存储在Data数组中

方式

方式1

string(bytes)或[]byte(str)
性能不佳

方式2

// toBytes performs unholy acts to avoid allocations
func toBytes(s string) []byte {return *(*[]byte)(unsafe.Pointer(&s))
}
// toString performs unholy acts to avoid allocations
func toString(b []byte) string {return *(*string)(unsafe.Pointer(&b))
}

方式3

func SliceByteToString(b []byte) string {return *(*string)(unsafe.Pointer(&b))
}
func StringToSliceByte(s string) []byte {x := (*[2]uintptr)(unsafe.Pointer(&s))h := [3]uintptr{x[0], x[1], x[1]}return *(*[]byte)(unsafe.Pointer(&h))
}

方式4

func Clone(s string) string {if len(s) == 0 {return ""}b := make([]byte, len(s))copy(b, s)return *(*string)(unsafe.Pointer(&b))
}

性能测试

var L = 1024 * 1024
var str = strings.Repeat("a", L)
var s = bytes.Repeat([]byte{'a'}, L)
var str2 string
var s2 []byte
func BenchmarkString2Slice(b *testing.B) {for i := 0; i < b.N; i++ {bt := []byte(str)if len(bt) != L {b.Fatal()}}
}
func BenchmarkString2SliceReflect(b *testing.B) {for i := 0; i < b.N; i++ {bt := *(*[]byte)(unsafe.Pointer(&str))if len(bt) != L {b.Fatal()}}
}
func BenchmarkString2SliceUnsafe(b *testing.B) {for i := 0; i < b.N; i++ {bt := unsafe.Slice(unsafe.StringData(str), len(str))if len(bt) != L {b.Fatal()}}
}
func BenchmarkSlice2String(b *testing.B) {for i := 0; i < b.N; i++ {ss := string(s)if len(ss) != L {b.Fatal()}}
}
func BenchmarkSlice2StringReflect(b *testing.B) {for i := 0; i < b.N; i++ {ss := *(*string)(unsafe.Pointer(&s))if len(ss) != L {b.Fatal()}}
}
func BenchmarkSlice2StringUnsafe(b *testing.B) {for i := 0; i < b.N; i++ {ss := unsafe.String(unsafe.SliceData(s), len(str))if len(ss) != L {b.Fatal()}}
}

官方出品必然是好东西,所以相信GO1.21即可

参考

https://colobu.com/2022/09/06/string-byte-convertion/
https://pkg.go.dev/unsafe#String

http://www.lryc.cn/news/235955.html

相关文章:

  • 所见即所得的动画效果:Animate.css
  • ERR:Navicat连接Sql Server报错
  • python算法例10 整数转换为罗马数字
  • springboot引入第三方jar包放到项目目录中,添加web.xml
  • 大数据研发工程师课前环境搭建
  • Qt图形视图框架:QGraphicsItem详解
  • defer和async
  • 数电实验-----实现74LS139芯片扩展为3-8译码器以及应用(Quartus II )
  • 洋葱架构、三层架构及两者区别
  • JavaEE进阶学习:Spring 的创建和使用
  • 音视频项目—基于FFmpeg和SDL的音视频播放器解析(十四)
  • Tomcat无法映射到activiti-app导致activiti无法启动页面
  • c语言常见的面试问题
  • image图片之间的间隙消除
  • asp.net心理健康管理系统VS开发sqlserver数据库web结构c#编程计算机网页项目
  • CnosDB有主复制演进历程
  • 【前沿学习】美国零信任架构发展现状与趋势研究
  • Toolformer论文阅读笔记(简略版)
  • Pytorch torch.dot、torch.mv、torch.mm、torch.norm的用法详解
  • Jave 定时任务:使用Timer类执行定时任务为何会发生任务阻塞?如何解决?
  • Visual Studio Code配置c/c++环境
  • 漏洞利用工具的编写
  • ChatGPT之父被OpenAI解雇
  • linux中利用fork复制进程,printf隐藏的缓冲区,写时拷贝技术,进程的逻辑地址与物理地址
  • java游戏制作-拼图游戏
  • 使用sklearn报AttributeError: ‘NoneType‘ object has no attribute ‘split‘
  • C++学习 --map
  • 基于Qt QList和QMap容器类示例
  • Flask学习一:概述
  • LeetCode:689. 三个无重叠子数组的最大和(dp C++)