一个字符串是一个不可改变的字节序列,字符串可以包含任意数据,文本字符串通常被解释为采用UTF8编码的Unicode码点(rune)序列
表现形式
golang中的字符串支持两种表现形式
func TestString(t *testing.T) {
// 形式一: 双引号,会识别转义字符
str1 := "这是字符串的表现形式一。\n你可以看到换行了"
// 形式二: 反引号,以字符串的原生形式输出,包括换行和特殊字符,可以防止攻击,输出源代码等效果
str2 := `源代码
func TestInt1(t *testing.T) {
var i uint8 = 0
i--
fmt.Println(i) // 255
}
`
fmt.Println(str1)
fmt.Println(str2)
}
零值
golang中的字符串是值类型,零值/默认值是空字符串""
func TestString(t *testing.T) {
var str1 string
fmt.Println(str1 == "") // true
}
长度
内置的len函数,计算的是字符串中的字节的数量,不是字符的数量
一个中文字符可能占多个字节数,可以使用utf8.RuneCountInString计算字符串中字符的数量
func TestString(t *testing.T) {
// 一个中文字符可能占用多个字节
str := "hello,上海"
fmt.Println(len(str)) // 12,展示的是字节数,不是字符数
fmt.Println(utf8.RuneCountInString(str)) // 8,展示的是字符数
}
操作
索引操作s[i]返回第i个字节的字节值,i必须满足0 ≤ i< len(s)条件约束
注意:第i个字节并不一定是字符串的第i个字符,因为对于非ASCII字符的UTF8编码会要两个或多个字节
func TestString(t *testing.T) {
// 一个中文字符可能占用多个字节
str := "hello,上海"
// 索引操作s[i]返回第i个字节的字节值,i必须满足0 ≤ i< len(s)条件约束
fmt.Println(str[0]) // 104
}
子字符串操作s[i:j]基于原始的s字符串的第i个字节开始到第j个字节(并不包含j本身)生成一个新字符串,生成的新字符串将包含j-i个字节
不管i还是j都可能被忽略,当它们被忽略时将采用0作为开始位置,采用len(s)作为结束的位置
func TestString(t *testing.T) {
// 一个中文字符可能占用多个字节
str := "hello,上海"
// 字符串截取
fmt.Println(str[0:5]) // hello
// 等价于str[0:9]
fmt.Println(str[:9]) // hello,上
// 等价于str[6:len(str)]
fmt.Println(str[6:]) // 上海
}
字符串可以用==和<进行比较;比较通过逐个字节比较完成的,因此比较的结果是字符串自然编码的顺序
unicode和utf8
unicode:每个符号都分配一个唯一的Unicode码点,Unicode码点对应Go语言中的rune整数类型(译注:rune是int32等价类型)。我们可以将一个符文序列表示为一个int32序列。这种编码方式叫UTF-32或UCS-4,每个Unicode码点都使用同样大小的32bit来表示。这种方式比较简单统一,但是它会浪费很多存储空间,因为大多数计算机可读的文本是ASCII字符,本来每个ASCII字符只需要8bit或1字节就能表示
utf8:UTF8是一个将Unicode码点编码为字节序列的变长编码。UTF8编码是由Go语言之父Ken Thompson和Rob Pike共同发明的,现在已经是Unicode的标准。UTF8编码使用1到4个字节来表示每个Unicode码点,ASCII部分字符只使用1个字节,常用字符部分使用2或3个字节表示
Go语言的源文件采用UTF8编码
遍历
如果字符串中含有中文字符,遍历的时候一定不要按照字节遍历,一定要按照字符来遍历
func TestString(t *testing.T) {
str := "hello,上海"
// 方式一:直接使用range,按照字符遍历
for i, v := range str {
fmt.Printf("%d : %c\n", i, v)
}
// 方式二:转换成rune切片,按照字符遍历
runes := []rune(str)
for i, v := range runes {
fmt.Printf("%d : %c\n", i, v)
}
}
有疑问加站长微信联系(非本文作者)