1、什麼是字元串? Go語言中字元串是一個位元組切片。把內容放在雙引號""之間,我們可以創建一個字元串,讓我們來看一下創建並列印字元串的簡單示例。 package main import ( "fmt" ) func main() { str := "hello golang" fmt.Println ...
1、什麼是字元串?
Go語言中字元串是一個位元組切片。把內容放在雙引號""之間,我們可以創建一個字元串,讓我們來看一下創建並列印字元串的簡單示例。
package main import ( "fmt" ) func main() { str := "hello golang" fmt.Println(str) }
線上運行程式
hello golang
2、獲取字元串的每一個位元組
由於字元串是一個位元組切片,所以我們可以獲取字元串的每一個位元組
package main import ( "fmt" ) func main() { str := "hello golang" printChars(str) fmt.Println() printBytes(str) fmt.Println() printCharsAndBytes(str) } // 位元組 %x 限定列印字元串位元組 func printBytes(s string) { for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) } } // 字元 %c 限定列印字元串的字元 func printChars(s string) { for i := 0; i < len(s); i++ { fmt.Printf("%c ", s[i]) } } // for range 迴圈是最簡單方法方 func printCharsAndBytes(s string) { for _, rune := range s { fmt.Printf("%c starts at byte %x\n", rune, rune) } }
線上運行程式
h e l l o g o l a n g 68 65 6c 6c 6f 20 67 6f 6c 61 6e 67 h starts at byte 0 e starts at byte 1 l starts at byte 2 l starts at byte 3 o starts at byte 4 starts at byte 5 g starts at byte 6 o starts at byte 7 l starts at byte 8 a starts at byte 9 n starts at byte a g starts at byte b airdeMacBook-Air:learn_demo wutianxiang$ go run main.go h e l l o g o l a n g 68 65 6c 6c 6f 20 67 6f 6c 61 6e 67 h starts at byte 68 e starts at byte 65 l starts at byte 6c l starts at byte 6c o starts at byte 6f starts at byte 20 g starts at byte 67 o starts at byte 6f l starts at byte 6c a starts at byte 61 n starts at byte 6e g starts at byte 67
如果我們再上面基礎上字元串含中文,那會如何?
package main import ( "fmt" ) func main() { str := "hello golang 語言" printChars(str) fmt.Println() printBytes(str) fmt.Println() printCharsAndBytes(str) } // 位元組 %x 限定列印字元串位元組 func printBytes(s string) { for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) } } // 字元 %c 限定列印字元串的字元 func printChars(s string) { for i := 0; i < len(s); i++ { fmt.Printf("%c ", s[i]) } } // for range 迴圈是最簡單方法方 func printCharsAndBytes(s string) { for _, rune := range s { fmt.Printf("%c starts at byte %x\n", rune, rune) } }
線上運行程式
h e l l o g o l a n g è ¯ è ¨ 68 65 6c 6c 6f 20 67 6f 6c 61 6e 67 20 e8 af ad e8 a8 80 h starts at byte 68 e starts at byte 65 l starts at byte 6c l starts at byte 6c o starts at byte 6f starts at byte 20 g starts at byte 67 o starts at byte 6f l starts at byte 6c a starts at byte 61 n starts at byte 6e g starts at byte 67 starts at byte 20 語 starts at byte 8bed 言 starts at byte 8a00
上面第一行輸出了錯誤 h e l l o g o l a n g è ¯ è ¨
為什麼程式分割 hello golang 時表現完美,但分割字元含中文就錯誤?
這是“語言”的unicode代碼點(code point)是U+00F1。他的UTF-8編碼占用了 e8 af ad e8 a8 80
6個位元組。
它的UTF-8編碼占用了8個位元組 e8 af ad e8 a8 80。而我們列印字元時,卻假定每個字元的編碼只會占用一個位元組,這是錯誤的。
在UTF-8編碼中,一個代碼點可能會占用超過一個位元組的空間。
那麼我們該怎麼辦呢?
rune 能幫我們解決這個難題。
rune是Go語言的內建類型,它是int32的別稱。在Go語言中,rune表示一個代碼點,無論代碼點占用多少個位元組,都可以用一個rune來表示。
package main import ( "fmt" ) func main() { str := "hello golang 語言" printChars(str) fmt.Println() printBytes(str) fmt.Println() printCharsAndBytes(str) } // 位元組 %x 限定列印字元串位元組 func printBytes(s string) { for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) } } // 字元 %c 限定列印字元串的字元 func printChars(s string) { runes := []rune(s) for i := 0; i < len(runes); i++ { fmt.Printf("%c ", runes[i]) } } // for range 迴圈是最簡單方法方 func printCharsAndBytes(s string) { for _, rune := range s { fmt.Printf("%c starts at byte %x\n", rune, rune) } }
線上運行程式
h e l l o g o l a n g 語 言 68 65 6c 6c 6f 20 67 6f 6c 61 6e 67 20 e8 af ad e8 a8 80 h starts at byte 68 e starts at byte 65 l starts at byte 6c l starts at byte 6c o starts at byte 6f starts at byte 20 g starts at byte 67 o starts at byte 6f l starts at byte 6c a starts at byte 61 n starts at byte 6e g starts at byte 67 starts at byte 20 語 starts at byte 8bed 言 starts at byte 8a00
3、用位元組切片構造字元串
package main import ( "fmt" ) func main() { // 十六進位 byteSlice := []byte{0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x67, 0x6F, 0x6C, 0x61, 0x6E, 0x67, 0x20, 0xE8, 0xAF, 0xAD, 0xE8, 0xA8, 0x80} str := string(byteSlice) fmt.Println(str) }
線上運行程式
hello golang 語言
4、rune 切片構造字元串
package main import ( "fmt" ) func main() { runeSlice := []rune{104, 101, 108, 108, 111, 32, 103, 111, 108, 97, 110, 103, 32, 35821, 35328} str := string(runeSlice) fmt.Println(str) }
線上運行程式
hello golang 語言
5、獲取字元串長度
對於字母數字組合成字元串獲取長度,用len()方法;
對於中文或其它國家文字組成字元串獲取長度,用utf8.RuneCountInString()方法
package main import ( "fmt" "unicode/utf8" ) func main() { str1 := "hello" length(str1) str2 := "hello您好" length(str2) } // 獲取字元串長度 func length(s string) { fmt.Printf("length of %s is %d\n", s, utf8.RuneCountInString(s)) }
6、字元串是不可變的。一旦創建一個字元串,那麼他將無法被修改。如果試圖把字元串修改,程式會拋出一個錯誤:cannot assign to s[0]
package main import ( "fmt" ) func main() { str := "hello" fmt.Println(midfyString(str)) } // 修改字元串 func midfyString(s string) string { s[0] = 'a' return s }
上面這個操作是非法的。
那麼如果修改字元,可以把字元串轉化一個rune切片,然後對這個切片任何修改,再將轉化一個新的字元串
package main import ( "fmt" ) func main() { str := "hello" fmt.Println(midfyString(str)) fmt.Println(str) } // 修改字元串 func midfyString(s string) string { runes := []rune(s) // 註意這個是單引號。如果改成雙引號,可以試試發生什麼 runes[0] = 'a' return string(runes) }
7、字元串拼接,後續。。