我们知道Golang字符串可以用操作[]byte相同的方式来操作,可以用下标来访问,也可以取子串,用下标来访问的话,每个元素的类型是个byte(uint8),例如
func SubStr(s string, start, length int) string {
return s[start:start+length]
}
func main() {
str := "abcde12345"
char := str[3]
fmt.Println(char, reflect.ValueOf(char).Kind()) // 100 uint8
sub := str[3:7]
fmt.Println(sub) // de12
fmt.Println(SubStr("hello world!", 6, 5)) // world
str2 := "你好,China"
for i := 0; i < len(str2); i++ {
fmt.Println(i, str2[i], reflect.ValueOf(str2[i]).Kind())
/*
0 228 uint8
1 189 uint8
2 160 uint8
3 229 uint8
4 165 uint8
5 189 uint8
6 239 uint8
7 188 uint8
8 140 uint8
9 67 uint8
10 104 uint8
11 105 uint8
12 110 uint8
13 97 uint8
*/
}
}
从上面可以看出,Golang的字符串操作和把字符串转成[]byte之后的操作基本一致,除了取子串时一个返回的是字符串,一个返回的是另一个[]byte,但注意如果用for…range来遍历一个字符串,表现则完全不同,这也是我们平时使用时需要注意的一点,例如:
func main() {
str := "你好,China"
for i, char := range str {
fmt.Println(i, char, reflect.ValueOf(char).Kind())
// 0 20320 int32
// 3 22909 int32
// 6 65292 int32
// 9 67 int32
// 10 104 int32
// 11 105 int32
// 12 110 int32
// 13 97 int32
}
}
for…range遍历字符串每个元素的类型是rune(int32),即utf-8字符对应的unicode码点,而索引是每个utf-8字符的第一个字节在字符串中的下标,对比下把字符串转换为[]rune的区别
func main() {
str := "你好,China"
unicodes := []rune(str)
for i, char := range unicodes {
fmt.Println(i, char, reflect.ValueOf(char).Kind())
// 0 20320 int32
// 1 22909 int32
// 2 65292 int32
// 3 67 int32
// 4 104 int32
// 5 105 int32
// 6 110 int32
// 7 97 int32
}
}
遍历出来的索引和for…range不同,所以平时的使用应特别注意用for…range来遍历一个字符串的奇怪表现,避免用错。