Go 中的字符串是兼容 Unicode 編碼的,而且使用 UTF-8 進行編碼,這樣每個Unicode字符根據代碼點的大小使用一、二、3或4個字節表示代碼點。
Go 語言中的字符串是一個字節切片,也就是說單個字符能夠被字節索引,咱們能夠假定每一個字符的編碼只會佔用一個字節。例如:數組
var s = "Hello world!" for i:= 0; i < len(s); i++ { fmt.Printf("%x ", s[i])//48 65 6c 6c 6f 20 77 6f 72 6c 64 21 }
若是是ASCII字符(用一個單一的UTF-8字節表示)(一個字節),這樣作沒有什麼問題,如果非ASCII字符?。
對於每個Unicode字符呢,佔用的字節大小不同,但是咱們怎麼知道每次取多少個字節的大小?
因此在Go語言中,我可使用rune來解決這個問題,無論這個字符佔多大的字節,均可以用一個rune來表示。
rune 是 Go 語言的內建類型,它也是 int32 的別稱。在 Go 語言中,rune 表示一個代碼點。編碼
package main import "fmt" func main() { var s = "Hello world!" runes := []rune(s) for i:= 0; i < len(runes); i++ { fmt.Printf("%c ",runes[i]) }//H e l l o w o r l d ! }
注:https://naveenr.net/unicode-character-set-and-utf-8-utf-16-utf-32-encoding/ 來理解一下什麼是 Unicode 和 UTF-8。spa
用字節切片構造字符串.net
byteSlice
包含字符串 Café
用 UTF-8 編碼後的 16 進制字節code
用字節切片構造字符串 package main import ( "fmt" ) func main() { byteSlice := []byte{0x43, 0x61, 0x66, 0xC3, 0xA9} str := string(byteSlice) fmt.Println(str)//Café
}
用 rune 切片構造字符串blog
runeSlice
包含字符串 Señor
的 16 進制的 Unicode 代碼點索引
package main import ( "fmt" ) func main() { runeSlice := []rune{0x0053, 0x0065, 0x00f1, 0x006f, 0x0072} str := string(runeSlice) fmt.Println(str)//Café
}
func main() { //字符串底層是一個byte數組,能夠作切片處理 str := "hello world!" //使用切片 slice := str[2:] fmt.Println("slice=",slice)//slice= llo world! }
獲取字符串的字節數:len(str)
方法返回包含在字符串文字中的字節數。token
package main
import "fmt"
func main() {
var greeting = "Hello world!"
fmt.Printf("String Length is: ")
fmt.Println(len(greeting)) //String Length is : 12
}
獲取字符串的字符個數:utf8 package 包中的 func RuneCountInString(s string) (n int)
方法用來獲取字符串的長度。這個方法傳入一個字符串參數而後返回字符串中的 rune 的數量。utf-8
package main import ( "fmt" "unicode/utf8" ) func length(s string) { fmt.Printf("length of %s is %d\n", s, utf8.RuneCountInString(s))} func main() { word1 := "Señor" length(word1)//length of Señor is 5 word2 := "Pets" length(word2)//length of Señor is 4 }
字符串的迭代有兩種方法unicode
package main import ( "fmt" )
//方法1,使用for range func printChars1(s string) { for index, rune := range s { fmt.Printf("%c starts at byte %d\n", rune, index) } }
//方法2 func printChars2(s string) { runes := []rune(s) for i:= 0; i < len(runes); i++ { fmt.Printf("%c ", runes[i]) } } func main() { name := "Señor" printChars1(name) printChars2(name) }
輸出結果:
S starts at byte 0 e starts at byte 1 ñ starts at byte 2 o starts at byte 4 r starts at byte 5 S e ñ o r
string 是不可變的,也就說不能經過 str[0] = 'w' 方式來修改字符串。
若是須要修改字符串,能夠先將 string -> []byte 或者 []rune -> 修改 -> 重寫轉成 stringpackage main import "fmt" func main() { //字符串底層是一個byte數組,能夠作切片處理 str := "zello world!" arr1 := []byte(str) arr1[0] = 'h' str = string(arr1) fmt.Println("str=",str) //轉換成byte後,能夠處理英文和數字,不能處理中文 //[]byte一個索引只能處理一個字節的數據,漢字超出範圍,會出現亂碼 //前面咱們提到[]rune能將全部字符用一個字節表示 arr2 := []rune(str) arr2[0] = '一' str = string(arr2) fmt.Println("str=",str) }
結果: str= hello world! str= 一ello world!
strings
包包含一個用於鏈接多個字符串的join()
方法,其語法以下:
strings.Join(sample, " ")
Join
鏈接數組的元素以建立單個字符串。第二個參數是分隔符,放置在數組的元素之間。
package main
import (
"fmt"
"strings"
)
func main() {
greetings := []string{"Hello","world!"}
fmt.Println(strings.Join(greetings, " "))//Hello world!
}