一個字元串是一個不可改變的位元組序列,字元串可以包含任意資料,文本字元串通常被解釋為采用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)
}
}