1. 程式人生 > 程式設計 >golang中你不知道的 string

golang中你不知道的 string

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