字符串是不可变字节(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: [痕]