15.1 Go语言的字符串类型
在Go语言中,无论是字符串常量、字符串变量还是代码中出现的字符串字面量,它们的类型都被统一设置为string
特点
- string类型的数据是不可变的
- 对string进行切片化后,Go编译器会为切片变量重新分配底层存储而不是共用string的底层存储
- string的底层的数据存储区仅能进行只读操作,一旦试图修改那块区域的数据,便会得到SIGBUS的运行时错误
- 零值可用
- 获取长度的时间复杂度是O(1)级别
- 支持通过+/+=操作符进行字符串连接
- 支持各种比较关系操作符:==、!= 、>=、<=、>和<
- 对非ASCII字符提供原生支持
- 原生支持多行字符串(使用 ``)
- 直接将string类型通过函数/方法参数传入也不会有太多的损耗,因为传入的仅仅是一个“描述符”,而不是真正的字符串数据
15.2 字符串的内部表示
//todo
15.3 字符串的高效构造
- 在能预估出最终字符串长度的情况下,使用预初始化的strings.Builder连接构建字符串效率最高;
- strings.Join连接构建字符串的平均性能最稳定,如果输入的多个字符串是以[]string承载的,那么strings.Join也是不错的选择;类似implode
- 使用操作符连接的方式最直观、最自然,在编译器知晓欲连接的字符串个数的情况下,使用此种方式可以得到编译器的优化处理;
- fmt.Sprintf虽然效率不高,但也不是一无是处,如果是由多种不同类型变量来构建特定格式的字符串,那么这种方式还是最适合的。
15.4 字符串相关的高效转换
下面两种互相转换都要分配新内存
[]byte
b := []byte(s)
ss := string(bb)
[]rune
r := []rune(s)
ss := string(rr)
无需额外分配新内存的转换方式
func convert() {
s := "中国欢迎您,北京欢迎您"
sl := []byte(s)
for _, v := range sl {
_ = v
}
}
func convertWithOptimize() {
s := "中国欢迎您,北京欢迎您"
for _, v := range []byte(s) {
_ = v
}
}
func stringForRangeCovertOptimize() {
fmt.Println(testing.AllocsPerRun(1, convert)) //1
fmt.Println(testing.AllocsPerRun(1, convertWithOptimize)) //0
}
关于rune的知识点
// rune is an alias for int32 and is equivalent to int32 in all ways. It is // used, by convention, to distinguish character values from integer values.
//int32的别名,几乎在所有方面等同于int32
//它用来区分字符值和整数值
type rune = int32
问题:string是怎么转成[]rune的呢?v是什么呢?
- string通过类型转换,来转成[]rune
- for range遍历string或[]rune时,v都表示每一个Unicode字符的值(rune类型)
s := "hi,你好吗"
r := []rune(s)
for i, v := range r {
fmt.Printf("%d %x\n", i, v)
}
for i, v := range s {
fmt.Printf("%d %x\n", i, v)
}
fmt.Printf("%x", s)
标签:int32,15,string,读书笔记,fmt,字符串,rune,Go
From: https://www.cnblogs.com/brynchen/p/18011129