golang——字符串與編碼


1、字符編碼

(1)ASCII碼

一個字節表示的英文、數字、標點符號等字符。

國際標准ASCII碼為0-127即128個字符,二進制最高位為0,其余為擴展ASCII碼。

(2)GB2312

兩字節,主要包含簡體的常用中文及符號的字符集編碼。

(3)GBK

單雙字節變長編碼,主要包含簡體繁體中文和一些符號、偏旁部首的字符集編碼。

(4)GB18030

GBK編碼無法滿足需求擴展,多出來的部分使用四字節編碼,即單、雙、四字節編碼;

擴展了漢字,還包括了少數民族文字;

(5)Unicode

因各國語言、字符差異,Unicode將所有字符統一為一套字符集。

UTF-8、UTF-16、UTF-32是對Unicode字符集的不同編碼方案。

(6)UTF-8

變長編碼方式,1-4字節表示一個字符,可節省存儲空間;

英文1字節,中文一般3字節,最多4字節;

編碼規則:

》單字節:同標准ASCII碼,最高位為0,0-127表示128個字符

》多字節:n字節,高位到低位,第一字節前n位為1,第n+1位為0;后面字節前兩位為10;剩余位由低位向高位填補Unicode嗎,多出補0;

110XXXXX 10XXXXXX

1110XXXX 10XXXXXX 10XXXXXX

2、字符串遍歷

golang使用utf-8的編碼方式

2.1、for循環遍歷字符串

func main() {
	str := "test篤志弘毅"
	for i := 0; i < len(str); i++ {
		fmt.Printf("%v %c,", str[i], str[i])
	}
}
//116 t,101 e,115 s,116 t,231 ç,172 ¬,131 ƒ,229 å,191 ¿,151 —,229 å,188 ¼,152 ˜,230 æ,175 ¯,133 …,

  以下標訪問字符串時,按單字節(byte)訪問,超出單字節的編碼會出現亂碼。

2.2、for range遍歷字符串

func main() {
	str := "test篤志弘毅"
	for i, v := range str {
		fmt.Printf("%d-%c-%v ", i, v, v)
	}
}
//0-t-116 1-e-101 2-s-115 3-t-116 4-篤-31491 7-志-24535 10-弘-24344 13-毅-27589

  for range遍歷字符串時,按字符(rune)訪問,中文正常顯示

3、字符串轉字符切片字節切片的差異

func main() {
	str := "test篤志弘毅"
	runeS := []rune(str)
	for i := 0; i < len(runeS); i++ {
		fmt.Printf("%c-%v ", runeS[i], runeS[i])
	}
	fmt.Println()
	byteS := []byte(str)
	for i := 0; i < len(byteS); i++ {
		fmt.Printf("%c-%v ", byteS[i], byteS[i])
	}
}
//t-116 e-101 s-115 t-116 篤-31491 志-24535 弘-24344 毅-27589 
//t-116 e-101 s-115 t-116 ç-231 ¬-172 ƒ-131 å-229 ¿-191 —-151 å-229 ¼-188 ˜-152 æ-230 ¯-175 …-133

4、字符串注意點

(1)字符串的零值為空串"",不是nil

func main() {
	var str string
	fmt.Println(str == "") //true
	//fmt.Println(str == nil)
	//invalid operation: str == nil (mismatched types string and nil)
	//無效操作(string和nil類型不匹配)
}

(2)索引訪問或是切片得到的都是按字節處理,可能出現亂碼

(3)len函數返回的是字節數,而不是字符數  

func main() {
	str := "test篤志弘毅"
	fmt.Println(len(str))//16
}

(4)不能通過索引或指針修改字符串字符

func main() {
	str := "test篤志弘毅"
	str[2] = 'a'     //cannot assign to str[2]
	*(&str[2]) = 'b' // cannot take the address of str[2]
	fmt.Println(str)
}

(5)字符串的切片操作返回的是字符串,而不是切片

func main() {
	str := "test篤志弘毅"
	str1 := str[:]
	str2 := str[:]
	fmt.Printf("%T %p %p\n", str1, &str1, &str2)
}
//string 0xc0000581c0 0xc0000581d0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM