golang中你不知道的 string

golang中你不知道的 stringgit

字符串對於一篇博客文章來講彷佛太簡單了,可是一個簡單的東西想用好,其實也不容易。github

遍歷字符串

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
複製代碼

輸出的是每個字節。 若是想輸出字符呢?golang

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, value:%c \n", i, runeValue)
		s = size
	}
}
複製代碼

輸出bash

position:0, value:我 
position:3, 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 
複製代碼

還有更方便的嗎?ui

package main

import (
	"fmt"
)

func main() {
	const sample = "我愛golang"
	for key, v := range sample {
		fmt.Printf("position:%v, value:%c \n", key, v)
	}
}
複製代碼

輸出編碼

position:0, value:我 
position:3, 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 
複製代碼
  • 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")
}
複製代碼

輸出spa

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)
}
複製代碼

輸出code

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鏈接blog

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索引

相關文章
相關標籤/搜索