字符串是不可变字节(byte)序列,其本身是一个复合结构。
type stringStruct struct {
str unsafe.Pointer
len int
}
1.头部指针指向字节数组,但没有null结尾。默认以UFT-8编码存储Unicode字符,字面量里允许使用十六进制、八进制和UTF编码格式。
func main() {
s := "嘿嘿\x61\142\u0042"
fmt.Printf("%s\n", s)
fmt.Printf("% x, len: %d\n",s , len(s))
}
输出:
嘿嘿abB
e5 98 bf e5 98 bf 61 62 42, len: 9
内置函数len返回字节数组长度,cap不接受字符串类型参数。 字符串默认不是nil。而是""
2.使用" ` "定义不做转义处理的原始字符串,支持跨行。
func main() {
s := `line\r\n
lin2`
println(s)
}
输出:
line\r\n
lin2
3.支持!=、==、<、>、+、+=操作符.
func main() {
s := "abcd"
println(s == "abcd")
println(s > "abc")
}
输出:
true
true
4.允许以索引号访问字节数组(非字符),但不能获取元素地址
func main() {
s := "abcd"
println(s[1]) //输出 98
println(&s[1]) //编译报错cannot take the address of s[1]
}
5.以切片语法(起始和结束索引好)返回字串时,其内部依旧指向原字节数组。
func main() {
s := "abcd"
s1 := s[:3] //从头开始仅指定结束索引位置
s2 := s[1:4] //指定开始和结束位置,返回[start,end]
s3 := s[2:] //指定开始位置,返回后面全部内容
println(s1,s2,s3)
}
输出:
abc bcd cd
6.使用for循环遍历字符串时,分byte和rune两种方式。
func main() {
s := "傻蛋"
for i := 0; i < len(s); i++ { //byte
fmt.Printf("%d: [%c]\n", i, s[i])
}
for i, c := range s { //rune: 返回数组索引号,以及Unicode字符
fmt.Printf("%d: [%c]\n", i, c)
}
}
输出:
0: [å]
1: [�]
2: [»]
3: [è]
4: [�]
5: [�]
0: [傻]
3: [蛋]
- Unicode
类型rune
专门用来存储Unicode码点(code point),它是int32的别名,相当于UCS-4/UFT-32编码格式。使用单引号的字面量,其默认值是rune。
func main() {
r := '我'
fmt.Printf("%T\n", r)
}
输出:
int32
8.除[ ]rune外,还可以直接在rune、string、byte间进行转换。
func main() {
r := '我'
s := string(r)
b := byte(r)
s2 := string(b)
r2 := rune(b)
fmt.Println(s, b, s2, r2)
}
9.可用RuneCountInString代替len返回准确的Unicode字符数量。
func main() {
s := "哈.喽"
println(len(s), utf8.RuneCountInString(s))
}
输出:
7 3