字符串是不可变字节(byte)序列,其本身是一个复合结构。

type stringStruct struct {
   str unsafe.Pointer
   len int
}

头部指针指向字节数组,但没有 NULL(\0)结尾。默认以 UTF-8 编码存储 Unicode 字符,字面量里允许使用十六进制、八进制和 UTF 编码格式。

func main() { 
	s := "雨痕\x61\142\u0041"
 
	fmt.Printf("%s\n", s) // 雨痕abA
	fmt.Printf("%x, len: %d\n", s, len(s)) // e9 9b a8 e7 97 95 61 62 41, len: 9
}

内置函数 len 返回字节数组长度,内置函数 cap 不接受字符串类型参数。

字符串默认值不是 nil,而是""。

var s string
 
println(s == "") // true
println(s == nil) // 无效操作:s==nil(mismatched types string and nil)

使用 ` 定义不做转义处理的原始字符串(raw string),支持跨行。

s := `line\r\n,
   line 2` // 不转义,支持跨行

编译器不会解析原始字符串内的注释语句,且前置缩进空格也属字符串内容。

支持 !===<>++= 操作符。

允许以索引号访问字节数组(非字符),但不能获取元素地址。

s := "abc"
 
println(s[1]) // byte
println(&s[1]) // 错误:cannot take the address of s[1]

以切片语法(起始和结束索引号)返回子串时,其内部依旧指向原字节数组。

s := "abcdefg"
 
s1 := s[1:] // 内部指向原字节数组

使用 for 遍历字符串时,分 byte 和 rune 两种方式。

s := "雨痕"
 
for i := 0; i < len(s); i++ { // byte
	fmt.Printf("%d: [%c]\n", i, s[i]) 
} 
 
fmt.Println()
 
for i, c := range s { //rune: 返回数组索引号,以及Unicode字符
	fmt.Printf("%d: [%c]\n", i, c)
}

输出:

0: [é]
1: []
2: [¨]
3: [ç]
4: []
5: []
 
0: [雨]
3: [痕]

转换