4.6 字符串
字符串是 UTF-8 字符的一個序列(當字符爲 ASCII 碼時則佔用 1 個字節,其它字符根據需要佔用 2-4 個字節)。UTF-8 是被廣泛使用的編碼格式,是文本文件的標準編碼,其它包括 XML 和 JSON 在內,也都使用該編碼。由於該編碼對佔用字節長度的不定性,Go 中的字符串也可能根據需要佔用 1 至 4 個字節(示例見第 4.6 節),這與其它語言如 C++、Java 或者 Python 不同(Java 始終使用 2 個字節)。Go 這樣做的好處是不僅減少了內存和硬盤空間佔用,同時也不用像其它語言那樣需要對使用 UTF-8 字符集的文本進行編碼和解碼。
字符串是一種值類型,且值不可變,即創建某個文本後你無法再次修改這個文本的內容;更深入地講,字符串是字節的定長數組。
Go 支持以下 2 種形式的字面值:
解釋字符串:
該類字符串使用雙引號括起來,其中的相關的轉義字符將被替換,這些轉義字符包括:
\n
:換行符\r
:回車符\t
:tab 鍵\u
或\U
:Unicode 字符\\
:反斜槓自身
非解釋字符串:
該類字符串使用反引號括起來,支持換行,例如:
`This is a raw string \n` 中的 `\n\` 會被原樣輸出。
和 C/C++不一樣,Go 中的字符串是根據長度限定,而非特殊字符\0
。
string
類型的零值爲長度爲零的字符串,即空字符串 ""
。
一般的比較運算符(==
、!=
、<
、<=
、>=
、>
)通過在內存中按字節比較來實現字符串的對比。你可以通過函數 len()
來獲取字符串所佔的字節長度,例如:len(str)
。
字符串的內容(純字節)可以通過標準索引法來獲取,在中括號 []
內寫入索引,索引從 0 開始計數:
- 字符串 str 的第 1 個字節:
str[0]
- 第 i 個字節:
str[i - 1]
- 最後 1 個字節:
str[len(str)-1]
需要注意的是,這種轉換方案只對純 ASCII 碼的字符串有效。
注意事項 獲取字符串中某個字節的地址的行爲是非法的,例如:&str[i]
。
字符串拼接符 +
兩個字符串 s1
和 s2
可以通過 s := s1 + s2
拼接在一起。
s2
追加在 s1
尾部並生成一個新的字符串 s
。
你可以通過以下方式來對代碼中多行的字符串進行拼接:
str := "Beginning of the string " +
"second part of the string"
由於編譯器行尾自動補全分號的緣故,加號 +
必須放在第一行。
拼接的簡寫形式 +=
也可以用於字符串:
s := "hel" + "lo,"
s += "world!"
fmt.Println(s) //輸出 “hello, world!”
在循環中使用加號 +
拼接字符串並不是最高效的做法,更好的辦法是使用函數 strings.Join()
(第 4.7.10 節),有沒有更好地辦法了?有!使用字節緩衝(bytes.Buffer
)拼接更加給力(第 7.2.6 節)!
在第 7 章,我們會講到通過將字符串看作是字節(byte)的切片(slice)來實現對其標準索引法的操作。會在第 5.4.1 節中講到的 for 循環只會根據索引返回字符串中的純字節,而在第 5.4.4 節(以及第 7.6.1 節的示例)將會展示如何使用 for-range 循環來實現對 Unicode 字符串的迭代操作。在下一節,我們會學習到許多有關字符串操作的函數和方法,同時 fmt
包中的 fmt.Sprint(x)
也可以格式化生成並返回你所需要的字符串(第 4.4.3 節)。
練習 4.6 count_characters.go
創建一個用於統計字節和字符(rune)的程序,並對字符串 asSASA ddd dsjkdsjs dk
進行分析,然後再分析 asSASA ddd dsjkdsjsこん dk
,最後解釋兩者不同的原因(提示:使用 unicode/utf8
包)。
鏈接
- 目錄
- 上一節:基本類型和運算符
- 下一節:strings 和 strconv 包