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

Go 1.21

go 复制代码
// 返回一个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 高效互转场景

go 复制代码
// 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 uintptr
    Len  int
    Cap  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 uintptr
    Len  int
}

Slice比String多一个Cap字段

两个的数据都存储在Data数组中

方式

方式1

string(bytes)或\[\]byte(str)

性能不佳

方式2

go 复制代码
// 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

go 复制代码
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

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

性能测试

go 复制代码
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

相关推荐
我的xiaodoujiao17 分钟前
快速学习Python基础知识详细图文教程18--多线程
开发语言·python·学习·测试工具
想要入门的程序猿31 分钟前
Qt插件QPluginLoader
开发语言·qt
Rabitebla1 小时前
C++11 新特性详解(一):列表初始化、initializer_list 与右值引用
java·开发语言·数据结构·c++·算法·leetcode·list
洋不写bug1 小时前
JavaComparable、Comparator、Cloneable接口解析,深拷贝浅拷贝详细解析
android·java·开发语言
吴声子夜歌1 小时前
正则指引——Golang
开发语言·golang·正则表达式
坐吃山猪1 小时前
WebFlux_学习Subscriber总结
java·开发语言·学习·webflux
乐橙开放平台1 小时前
一周上线校园透明化:listDeviceDetailsByPage 台账 + getKitToken + ImouPlayer 多路墙
后端·物联网·安全·音视频·智能家居
白露与泡影1 小时前
Java面试题及答案整理(2026年金九银十最新版,持续更新)
java·开发语言
樊小肆1 小时前
# 你还在等DeepSeek官方 agent Harness‌? 来试试 DeepSeeker-Code吧
前端·人工智能·后端
樊小肆1 小时前
2568 万 token 才花 2 块 2:聊聊 DeepSeeker-Code 怎么吃满上下文缓存
前端·人工智能·后端