golang中string和[]byte的区别与转换

它们是什么

在go标准库,src/builtin/builtin.go中有如下代码

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8

可以看到byte就是uint8的别名

在src/runtime/slice.go里,对slice的定义如下

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

对于string,我们可以在src/builtin/builtin.go和src/runtime/string.go中找到如下代码

// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string
type stringStruct struct {
	str unsafe.Pointer
	len int
}

区别

最大的区别就是string是immutable的,也就是不可修改的,看如下代码

// 能够通过编译
a := []byte{'1','2','3'}
a[1] = '4'

// 不能通过编译
b := "123"
b[1] = '4'

// 只能有以下操作
b = "143"

转换

普通转换代码

s1 := "hello"
// string转[]byte
b := []byte(s1)
// []byte转string
s2 := string(b)

实现细节见src/runtime/string.go中的stringtoslicebyte函数和slicebytetostring函数

简单来说,超过32个字节时,会发生一次内存分配,由此带来的分配时间和GC时间,包括一些安全检查,拖慢了整个程序运行的速度

强转换

func StringToBytes(s string) []byte {
	sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
	bh := reflect.SliceHeader{
		Data: sh.Data,
		Len: sh.Len,
		Cap: sh.Len,
	}
	return *(*[]byte)(unsafe.Pointer(&bh))
}

func BytesToString(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}

强转换就是和C语言的类型强制转化差不多的思想

场景

只读场景下可以使用

发表评论

邮箱地址不会被公开。 必填项已用*标注