Golang中Unicode與UTF-8有什么區(qū)別,很多新手對此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站建設(shè)、做網(wǎng)站、卓資網(wǎng)絡(luò)推廣、重慶小程序開發(fā)、卓資網(wǎng)絡(luò)營銷、卓資企業(yè)策劃、卓資品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供卓資建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com
Unicode 與 UTF-8 編碼
下面的圖來自 UTF-8 的截圖:
這幅圖簡單明了的告訴我們,UTF-8 的編碼方式,比如漢字一般用三個(gè) Byte,每個(gè) Byte 的開頭都是固定的,各種文字軟件解析 UTF-8 編碼的時(shí)候,它就會(huì)按照這個(gè)格式去解析,一旦解析錯(cuò)誤(畢竟還可能會(huì)有不符合要求的數(shù)據(jù),或者是文件錯(cuò)誤了),錯(cuò)誤的字節(jié)就會(huì)被替換為 “?” (U+FFFD),然后神奇的地方就來了: 即使遇到這種錯(cuò)誤,它也不會(huì)影響接下來的其他字符的解析 ,因?yàn)檫@種編碼不必從頭開始,使得它可以 自我同步(Self-synchronizing) 。與此同時(shí),其它的一些編碼一旦遇到錯(cuò)誤編碼就會(huì)出問題,導(dǎo)致錯(cuò)誤編碼之后的正確編碼也會(huì)跟著出錯(cuò)。
當(dāng)然,UTF-8 編碼也有缺點(diǎn),由于它是可變的,當(dāng)英文字符偏多的時(shí)候,它會(huì)省空間,然而比如當(dāng)中文偏多的時(shí)候,它理論上(3 Byte)會(huì)比 GBK 編碼(2 Byte)最多多出 1/3 的存儲(chǔ)空間。
UTF-8 的例子
我們拿 Unicode 中最受歡迎的 Emoji 表情 :joy: 1 來舉例:它的 Code point 是 U+1F602 (對, 1F602 是以 16 進(jìn)制表示的),然而在內(nèi)存中它的存儲(chǔ)方式的卻是 0xf09f9882 ,為什么?這就是 UTF-8 的編碼了(注意對比上圖的編碼方式):
000 011111 011000 000010 1f602 11110000 10011111 10011000 10000010 f0 9f 98 82
通過把 UTF-8 的編碼格子里面數(shù)據(jù)提取出來,我們就能獲得 Code point 1F602 。
你也可以用 Golang 來查看其它字符的編碼:
package main import ( "fmt" "unicode/utf8" )func main() { fmt.Printf("%b\n", []byte(`:joy:`)) fmt.Printf("% x\n", []byte(`:joy:`)) r, _ := utf8.DecodeRuneInString(`:joy:`) fmt.Printf("% b\n", r) fmt.Printf("% x\n", r) }
Unicode 的其他編碼
Unicode 當(dāng)然不止一種編碼,還有 UTF-16、UTF-32 等,它們的關(guān)系就是 UTF-16 用 2 個(gè) Byte 來表示 UTF-8 分別用 1/2/3 個(gè) Byte 來表示的字符,然后 4 個(gè) Byte 與 UTF-8 一致,UTF-32 是完全用 4 個(gè) Byte 來表示所有的字符,另外,詳細(xì)的可以在 Comparison of Unicode encodings 中看到,
好,基礎(chǔ)講完,現(xiàn)在開始正式介紹。
Unicode 與 Golang 2
這里特別需要提到的是 Golang 與 UTF-8 的關(guān)系,他們背后的男人,都是 Ken Thompson 跟 Rob Pike 3 4 5 ,由此,大家就會(huì)明白 Golang 的 UTF-8 設(shè)計(jì)是有多么重要的參考意義。比如 Golang 設(shè)計(jì)了一個(gè) rune 類型來取代 Code point 的意義。
rune 看源碼就知道,它就是 int32,剛好 4 個(gè) Byte,剛可以用來表示 Unicode 的所有編碼 UTF-8 與 UTF-16。
在繼續(xù)之前,我想幫各位明白一個(gè)事實(shí):Golang 的源碼是默認(rèn) UTF-8 編碼的,這點(diǎn)從上面我給出的例子中就能明白,所以表情字符在編譯的時(shí)候,就已經(jīng)能被解析。
好了,那么我們來看看 Golang 的 unicode 包,其中就會(huì)有很多有用的判斷函數(shù):
func IsControl(r rune) bool func IsDigit(r rune) bool func IsGraphic(r rune) bool func IsLetter(r rune) bool func IsLower(r rune) bool func IsMark(r rune) bool func IsNumber(r rune) bool func IsPrint(r rune) bool func IsPunct(r rune) bool func IsSpace(r rune) bool func IsSymbol(r rune) bool func IsTitle(r rune) bool func IsUpper(r rune) bool
另外,在 src/unicode/tables.go 中,有大量的 Unicode 中,各類字符的 Code point 區(qū)間,會(huì)有比較大的參考價(jià)值。
再看看 unicode/utf8 包,這里面的函數(shù),大多數(shù)時(shí)候你都用不到,但是有這么幾類情況就需要你必須得用到了:
統(tǒng)計(jì)字符數(shù)量;
轉(zhuǎn)編碼,比如將 GBK 轉(zhuǎn)為 UTF-8;
判斷字符串是否是 UTF-8 編碼,或者是否含有不符合 UTF-8 編碼的字符;
后面兩個(gè)可以忽略,第一個(gè)需要特地提醒下:
s := `:joy:` fmt.Println(len(s))
這句輸出是什么?上面提過了,剛好就是 4。于是,你不能使用 len 來獲取字符數(shù)量,也就不能以此來判斷用戶輸入的字符是不是超過了系統(tǒng)的限制。另外,你也不能通過 s[0] 這樣的方式來獲取字符,因?yàn)檫@樣你只能取到這 4 個(gè) Byte 中的第一個(gè),也就是 0xf0 。
你應(yīng)該做的就是把 string 轉(zhuǎn)為 rune 數(shù)組,然后再去進(jìn)行字符的操作。
具體的使用方法就不細(xì)談了,相信你們能搞定。
另外,這里需要另外提示下,在 Node.js 中,string 本身就是 Unicode,而不是像 Golang 的 string 是二進(jìn)制,因此在這里可以認(rèn)為 Node.js 的 Buffer 才是 Golang 中的 string。
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。