golang中你不知道的 string
阿新 • • 發佈:2020-06-24
golang中你不知道的 string
字串對於一篇部落格文章來說似乎太簡單了,但是一個簡單的東西想用好,其實也不容易。
遍歷字串
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
const sample = "我愛golang"
for i := 0; i < len(sample); i++ {
runeValue,_ := utf8.DecodeRuneInString(sample[i:])
fmt.Printf("position:%v,value:%c \n",i,runeValue)
}
}
複製程式碼
position:0,value:我
position:1,value:�
position:2,value:�
position:3,value:愛
position:4,value:�
position:5,value:�
position:6,value:g
position:7,value:o
position:8,value:l
position:9,value:a
position:10,value:n
position:11,value:g
複製程式碼
輸出的是每一個位元組。 如果想輸出字元呢?
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
const sample = "我愛golang"
for i,s := 0,0; i < len(sample); i = i + s {
runeValue,size := utf8.DecodeRuneInString(sample[i:])
fmt.Printf("position:%v,runeValue)
s = size
}
}
複製程式碼
輸出
position:0,value:我
position:3,value:愛
position:6,value:g
複製程式碼
還有更方便的嗎?
package main
import (
"fmt"
)
func main() {
const sample = "我愛golang"
for key,v := range sample {
fmt.Printf("position:%v,key,v)
}
}
複製程式碼
輸出
position:0,value:g
複製程式碼
- golang字串是由位元組構成的,因此索引它們會產生位元組,而不是字元
- 通過unicode、utf-8等編碼方式,從[]byte中解碼字串
字串的長度
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
str := "我愛golang"
fmt.Println(len(str),"len bytes")
fmt.Println(utf8.RuneCountInString(str),"len characters") // 更快
fmt.Println(len([]rune(str)),"len characters")
}
複製程式碼
輸出
12 len bytes
8 len characters
8 len characters
複製程式碼
- golang對字串的底層處理,採用的是[]byte,實際儲存的值是一個uint8型別的;
- 採用UTF-8編碼英文字元,每個字元只佔用一個byte,而中文需要佔用3個byte,因此長度是12;
- utf8會自動判斷每個字元編碼佔用了幾個byte,很清晰的展示了 Golang 對 string 的處理原理;
- for range string 每次迭代會解碼一個 utf-8 編碼的字元。
修改字串
package main
import "fmt"
func main() {
str := "golang"
c := []byte(str)
c[0] = 'c'
s2 := string(c)
fmt.Println(s2)
}
複製程式碼
輸出
colang
複製程式碼
拼接字串
package main
import (
"bytes"
"fmt"
)
func main() {
str := "我愛"
str2 := "golang"
// 該方案每次合併會建立一個新的字串
fmt.Println(str + str2)
// 該方案更更快,直接連線底層的 []byte
var buffer bytes.Buffer
buffer.WriteString(str)
buffer.WriteString(str2)
fmt.Println(buffer.String())
}
複製程式碼
WriteString更快的原因,見原始碼直接底層[]byte連線
func (b *Buffer) WriteString(s string) (n int,err error) {
b.lastRead = opInvalid
m,ok := b.tryGrowByReslice(len(s))
if !ok {
m = b.grow(len(s))
}
return copy(b.buf[m:],s),nil
}
複製程式碼
參考
更多內容,歡迎關注我的Github。