积木成楼
首页 / golang

go design (四) string

2022-01-08 · golang · 约 7 分钟

golang 中 字符串 的设计

字符串是由字符组成的数组,C 语言中的字符串使用字符数组 char[] 表示。数组会占用一片连续的内存空间,而内存空间存储的字节共同组成了字符串,Go 语言中的字符串为一个只读的字节数组。

golang 中对于 字符串 的设计

string 数据结构

// reflect/value.go 
type StringHeader struct {
	Data uintptr
	Len  int
}

// slice 的定义
type SliceHeader struct {
	Data uintptr
	Len  int
	Cap  int
}

修改,拼接与类型转换

string 的修改

str := "string"
fmt.Println(reflect.TypeOf(str[0]).Name())// uint8 
//也就是说 通过 slice 方式去读取的是每一字节的数据
// 对于 中文获取 长字节 的字符,不能直接通过这种方式去获取

// 会触发编译错误 string 是只读不变的
// str[0] = '0'  cannot assign to str[0] (strings are immutable) 

s1 := []byte(str)
s1[1] = 'o'
fmt.Println(str,string(s1))// string soring

string 的拼接

str := "string"
// 方式一
str = str + "233"
// 方式二
str = strings.Join([]string{str, "233"}, "")
// 方式三
str = fmt.Sprintf("%s%s", str, "233")
// 方式四
var build strings.Builder
build.WriteString(str)
build.WriteString("233")
str = build.String()
// 方式五
var bt bytes.Buffer
bt.WriteString(str)
bt.WriteString("233")
str = bt.String()

string 的类型转换

//runtime/string.go
func slicebytetostring(buf *tmpBuf, ptr *byte, n int) (str string) {
	if n == 0 {
		// Turns out to be a relatively common case.
		// Consider that you want to parse out data between parens in "foo()bar",
		// you find the indices and convert the subslice to string.
		return ""
	}
	if raceenabled {
		racereadrangepc(unsafe.Pointer(ptr),
			uintptr(n),
			getcallerpc(),
			funcPC(slicebytetostring))
	}
	if msanenabled {
		msanread(unsafe.Pointer(ptr), uintptr(n))
	}
	if n == 1 {
		p := unsafe.Pointer(&staticuint64s[*ptr])
		if sys.BigEndian {
			p = add(p, 7)
		}
		stringStructOf(&str).str = p
		stringStructOf(&str).len = 1
		return
	}

	var p unsafe.Pointer
	if buf != nil && n <= len(buf) {
		p = unsafe.Pointer(buf)
	} else {
		p = mallocgc(uintptr(n), nil, false)
	}
	stringStructOf(&str).str = p
	stringStructOf(&str).len = n
	memmove(p, unsafe.Pointer(ptr), uintptr(n))
	return
}


func stringtoslicebyte(buf *tmpBuf, s string) []byte {
	var b []byte
	if buf != nil && len(s) <= len(buf) {
		*buf = tmpBuf{}
		b = buf[:len(s)]
	} else {
		b = rawbyteslice(len(s))
	}
	copy(b, s)
	return b
}

相关的小问题

runebyte 有什么区别?

← 返回文章列表