rune
、byte
和string
都是Go
的內置類型
byte
- byte是
uint8
的別名,在所有方面都等同於uint8
- 按慣例,它用於區分字節值和8位無符號整數值。
- byte是
rune
rune
是int32
的別名,在所有方面都等同於int32
- 按慣例,它用於區分字符值和整數值。
string
- string是所有8位字節字符串的集合,通常但不一定代表UTF-8編碼的文本
- 字符串可能爲空,但是不能爲
nil
- 字符串類型的值是不可變的
- 由上面得解釋我們大概可以明白
rune
可以表示得比byte
多string
類型的底層是一個byte
數組- 以上解釋都來此
Go
源碼註釋
-
剛剛上面標註了字節和字符,現在我們來梳理字符和字節的概念
-
存儲單位 字節
- 計算機存儲信息的最小單位,稱之爲位
bit
,二進制的一個0
或1
叫一位 - 計算機存儲容量基本單位是字節
Byte
,8個二進制位組成1
個字節
- 計算機存儲信息的最小單位,稱之爲位
-
信息表示單位 字符
- 字符 是一種符號,像 英文
a
和中文阿
就是不同字符 - 不同的字符在不同的編碼格式下,所需要的存儲單位不一樣
ASCLII
編碼中一個英文字母一字節,一個漢字兩字節UTF-8
編碼中 一個英文字母一字節,一個常見漢字3字節,不常用的超大字符集漢字4字節
- 字符 是一種符號,像 英文
Go
源碼文件默認採用Unicode
字符集,Unicode
碼點和內存中字節序列的變換實現使用了UTF-8
,這使得Go
編程無需考慮編碼轉換的問題非常方便- 從編碼上來分析
byte
用來強調一個字節代表的數據(例如字符a
就是97
),而不是數字;rune
用來表示Unicode
的碼點,即一個字符
- 通俗一點
byte
只能操作簡單的字符,不支持中文操作rune
能操作任何字符
- 代碼演示
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
str := "hello 世界!"
fmt.Println(str)
fmt.Println(len(str))
fmt.Println(utf8.RuneCountInString(str))
fmt.Println(str[1])
fmt.Println(string(str[1]))
fmt.Println(str[1:])
fmt.Println(str[7:])
}
*************************************
輸出
hello 世界!
13
9
101
e
ello 世界!
��界!
- 會輸出
hello 世界!
,這證明Go
是UTF-8
編碼的,輸出長度爲13
這說明了一個漢字3字節 - 輸出
ello 世界!
說明string
底層的數據結構是數組 - 輸出
��界!
說明string
底層是一個byte
數組,不然不會亂碼
package main
import "fmt"
func StrChangeByRune(str *string, i int, ch rune) {
temp := []rune(*str)
temp[i] = ch
*str = string(temp)
}
func StrChangeByByte(str *string, i int, ch byte) {
temp := []byte(*str)
temp[i] = ch
*str = string(temp)
}
func main() {
str := "你好 hello"
str1 := "你好 hello"
StrChangeByRune(&str, 1, 'A')
StrChangeByByte(&str1, 1, 'A')
fmt.Println(str)
fmt.Println(str1)
}
*******************************
輸出
你A hello
�A�好 hello
- 由輸出
你A hello
和�A�好 hello
可以看出 byte
的操作單位是一個字節,可以理解爲一個英文字符rune
的操作單位是一個字符,不管這個字符是什麼字符