任何語言中,字符串操作API都是非常重要的,有些還是熟記比較好,當然如果記不住可以去看源碼文件,不得不說GO語言源碼看起來非常舒服。
可以使用反引號代替雙引號,來表示原生的字符串,即不進行轉義,尤其適合用於表示正則表達式、路徑字符串、JSON串。
每個Unicode碼點都使用同樣的大小32bit來表示。這種方式比較簡單統一,但是它會浪費很多存儲空間,因為大數據計算機可讀的文本是ASCII字符,本來每個ASCII字符只需要8bit或1字節就能表示。而且即使是常用的字符也遠少於65,536個,也就是說用16bit編碼方式就能表達常用字符。
UTF8是一個將Unicode碼點編碼為字節序列的變長編碼。UTF8編碼由Go語言之父Ken Thompson和Rob Pike共同發明的,現在已經是Unicode的標准。UTF8編碼使用1到4個字節來表示每個Unicode碼點,ASCII部分字符只使用1個字節,常用字符部分使用2或3個字節表示。每個符號編碼后第一個字節的高端bit位用於表示總共有多少編碼個字節。如果第一個字節的高端bit為0,則表示對應7bit的ASCII字符,ASCII字符每個字符依然是一個字節,和傳統的ASCII編碼兼容。如果第一個字節的高端bit是110,則說明需要2個字節;后續的每個高端bit都以10開頭。更大的Unicode碼點也是采用類似的策略處理。
許多類型都會定義一個String方法,因為當使用fmt包的打印方法時,將會優先使用該類型對應的String方法返回的結果打印
go語言默認使用UTF-8編碼,對Unicode的支持非常好。其它語言中一般都提供獲取字符串長度的函數,但實際上是獲取字節個數,但獲取 Unicode 碼點個數就可能有些麻煩,比如注冊帳號時,無視中英文限制長度時,就要獲取Unicode碼點個數。GO語言內置了方法:
import "unicode/utf8" s := "Hello, 世界" fmt.Println(len(s)) // "13" fmt.Println(utf8.RuneCountInString(s)) // "9"
而遍歷輸出這些字符是這樣的:
for i := 0; i < len(s); { r, size := utf8.DecodeRuneInString(s[i:]) fmt.Printf("%d\t%c\n", i, r) i += size }
每一次調用DecodeRuneInString函數都返回一個r和長度,r對應字符本身,長度對應r采用UTF8編碼后的編碼字節數目。實際上,Go語言的range循環在處理字符串的時候,會自動隱式解碼UTF8字符串。
for i, r := range "Hello, 世界" { fmt.Printf("%d\t%q\t%d\n", i, r, r) }
string接受到[]rune的類型轉換,可以將一個UTF8編碼的字符串解碼為Unicode字符序列。
如果遇到非法的unicode字符,會解析成 \uFFFD,它是一個特殊符號,遇到它就要注意了。
標准庫中有四個包對字符串處理尤為重要:bytes、strings、strconv和unicode包。strings包提供了許多如字符串的查詢、替換、比較、截斷、拆分和合並等功能。
bytes包也提供了很多類似功能的函數,但是針對和字符串有着相同結構的[]byte類型。因為字符串是只讀的,因此逐步構建字符串會導致很多分配和復制。在這種情況下,使用bytes.Buffer類型將會更有效,稍后我們將展示。
strconv包提供了布爾型、整型數、浮點數和對應字符串的相互轉換,還提供了雙引號轉義相關的轉換。
unicode包提供了IsDigit、IsLetter、IsUpper和IsLower等類似功能,它們用於給字符分類。每個函數有一個單一的rune類型的參數,然后返回一個布爾值。而像ToUpper和ToLower之類的轉換函數將用於rune字符的大小寫轉換。所有的這些函數都是遵循Unicode標准定義的字母、數字等分類規范。strings包也有類似的函數,它們是ToUpper和ToLower,將原始字符串的每個字符都做相應的轉換,然后返回新的字符串。
字節數組 []byte 和 string 可以互相轉換,[]byte本質是一個數組(切片?),string是一個常量。bytes包和strings包提供了很多類似的函數,都是為了效率出發,避免轉換。bytes包還提供了Buffer類型用於字節slice的緩存。一個Buffer開始是空的,但是隨着string、byte或[]byte等類型數據的寫入可以動態增長,一個bytes.Buffer變量並不需要處理化,因為零值也是有效的:
當向bytes.Buffer添加任意字符的UTF8編碼時,最好使用bytes.Buffer的WriteRune方法,但是WriteByte方法對於寫入類似'['和']'等ASCII字符則會更加有效。
字符串操作相關的API大多封裝在 strings 包里,下面列一些常見的
func Count(s, sep string) int
獲取指定子字符串的個數
func Contains(s, substr string) bool
判斷是否包括某子字符串
func ContainsAny(s, chars string) bool
判斷是否包括某字符串中的做任意一個字符,只要包括其中任意一個字符則返回true
func EqualFold(s, t string) bool
忽略大小寫時,判斷兩個字符串是否相等。
func Fields(s string) []string
其實就是其它語言中的 Splite 函數,分隔字符串的,這個是按空格分隔。
func Split(s, sep string) []string
按指定字符分隔字符串
func FieldsFunc(s string, f func(rune) bool) []string
更強大的自定義分隔字符串,使用函數作為參數
s := "a,b,c d,e,f" slice1 := strings.FieldsFunc(s, func(c rune) bool { if c == ',' || c == ' ' { return true } return false }) print_array(slice1)
func HasPrefix(s, prefix string) bool
判斷是否以某字符串開頭
func HasSuffix(s, suffix string) bool
判斷是否以某字符串結尾
接合這個看源碼吧 http://www.widuu.com/archives/01/939.html