go之UTF-8

unicode

請先查看 字符編碼筆記:ASCII刹悴,Unicode 和 UTF-8

go的字符串是如何編碼的

根據(jù)golang官方博客https://blog.golang.org/strings的原文:

Go source code is always UTF-8.
A string holds arbitrary bytes.
A string literal, absent byte-level escapes, always holds valid UTF-8 sequences.

大致意思如下:

  • go中的代碼總是用UTF-8編碼,并且字符串能夠存儲任何字節(jié)
  • 沒有經(jīng)過字節(jié)級別的轉(zhuǎn)義攒暇,那么字符串是一個(gè)標(biāo)準(zhǔn)的utf8序列

byte和rune

在Go語言中土匀,一個(gè)string類型的值既可以被拆分為一個(gè)包含多個(gè)字符的序列([]rune),也可以被拆分為一個(gè)包含多個(gè)字節(jié)的序列([]byte)

rune是Go語言特有的一個(gè)基本數(shù)據(jù)類型形用,它的一個(gè)值就代表一個(gè)字符就轧,即:一個(gè)Unicode字符。比如田度,'G'妒御、'o'、'愛'镇饺、'好'乎莉、'者'代表的就都是一個(gè)個(gè)Unicode字符。rune的底層表達(dá)使用的是Unicode代碼點(diǎn),底層的存儲用UTF-8編碼

通過unicode部分我們已經(jīng)知道惋啃,UTF-8編碼方案會把一個(gè)Unicode字符編碼為一個(gè)長度在[1, 4]范圍內(nèi)的字節(jié)序列哼鬓。所以rune類型的值也可以由一個(gè)或多個(gè)字節(jié)來代表。

type rune = int32 //rune實(shí)際上就是int32類型的一個(gè)別名類型

舉幾個(gè)栗子

string轉(zhuǎn)[]byte/[]rune
str := "Go愛好者"
fmt.Printf("  => runes(char): %q\n", []rune(str))
fmt.Printf("  => runes(hex): %x\n", []rune(str))
fmt.Printf("  => bytes(hex): [% x]\n", []byte(str))

// output
=> runes(char): ['G' 'o' '愛' '好' '者']  //這里用%q來安全的轉(zhuǎn)義成單引號圍繞的字符字面值边灭,%s無法轉(zhuǎn)義成字符字面值
=> runes(hex): [47 6f 7231 597d 8005]
=> bytes(hex): [47 6f e7 88 b1 e5 a5 bd e8 80 85]

分析:

  • []rune中的前兩個(gè)元素即47和6f與[]byte中的前兩個(gè)元素是一致的异希,因?yàn)閁TF-8是兼容ASCII的,都用一個(gè)字節(jié)表示
  • []rune中的后三個(gè)元素分別對應(yīng)[]byte中的后九個(gè)元素绒瘦,其中連續(xù)的三個(gè)對應(yīng)[]rune中的一個(gè)称簿,因?yàn)閞une中的中文字符使用UTF-8編碼,占用三個(gè)字節(jié)椭坚,同時(shí)也是UTF-8編碼對應(yīng)Unicode碼點(diǎn)

如下是Unicode編碼中UTF-8的編碼規(guī)則

Unicode編碼(十六進(jìn)制) UTF-8 字節(jié)流(二進(jìn)制)
000000-00007F   0xxxxxxx
000080-0007FF   110xxxxx 10xxxxxx
000800-00FFFF   1110xxxx 10xxxxxx 10xxxxxx
010000-10FFFF   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

'愛'為例予跌,其對應(yīng)的Unicode編碼是16進(jìn)制的7231,對應(yīng)二進(jìn)制111001000110001善茎, 那怎么對應(yīng)上[]byte中的e7 88 b1呢券册?
這里有一個(gè)轉(zhuǎn)換過程,如下:

  • 因?yàn)?x010000> 0x7231 > 0x07FF垂涯,所以套用UTF-8的模板是1110xxxx 10xxxxxx 10xxxxxx
  • 根據(jù)模板中x數(shù)量對特殊字符的高位補(bǔ)0烁焙。x的數(shù)量是16,所以需要對111001000110001的高位補(bǔ)1個(gè)0耕赘,此時(shí)特殊字符的二進(jìn)制表示為:0111001000110001
  • 模板中包含x的有3個(gè)部分骄蝇,且長度分別是4、6和6操骡,所以0111001000110001由底位向高位分別截取6九火、6和4位,得到110001册招、0010000111
  • 將得到的截取位依次填充至模板岔激,可得到UTF-8的完整二進(jìn)制序列為:11100111 10001000 10110001,也就對應(yīng)上了e7 88 b1
整數(shù)轉(zhuǎn)string

通過上面已知是掰,'愛'的Unicode編碼對應(yīng)16進(jìn)制是7231虑鼎,換算成整數(shù)就是29233

fmt.Printf("%q\n", 29233)
// output
'愛'

所以我們?nèi)绻麑φ麛?shù)進(jìn)行強(qiáng)制轉(zhuǎn)換成string,需要注意是否是對應(yīng)的合法的Unicode碼點(diǎn)

str := string(235234234234)
fmt.Printf("%q\n", str)
// output
"?"

這里因?yàn)?code>235234234234不是合法的Unicode碼點(diǎn)键痛,所以強(qiáng)制轉(zhuǎn)換后的結(jié)果是非預(yù)期的

for...range處理字符串

見代碼:

str := "go炫彩,你好"
for i, v := range str  {
    fmt.Printf("%d %q\n", i, v)
}
// output
// 注意這里輸出的索引值是以字節(jié)為跨度計(jì)算的
0 'g'
1 'o'
2 ','
5 '你'
8 '好'

帶有range子句的for語句會先把被遍歷的字符串值拆成一個(gè)字節(jié)序列絮短,然后再試圖找出這個(gè)字節(jié)序列中包含的每一個(gè)UTF-8編碼值江兢,或者說每一個(gè)Unicode字符

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市丁频,隨后出現(xiàn)的幾起案子划址,更是在濱河造成了極大的恐慌扔嵌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夺颤,死亡現(xiàn)場離奇詭異痢缎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)世澜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門独旷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人寥裂,你說我怎么就攤上這事嵌洼。” “怎么了封恰?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵麻养,是天一觀的道長。 經(jīng)常有香客問我诺舔,道長鳖昌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任低飒,我火速辦了婚禮许昨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘褥赊。我一直安慰自己糕档,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布拌喉。 她就那樣靜靜地躺著速那,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尿背。 梳的紋絲不亂的頭發(fā)上端仰,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音残家,去河邊找鬼榆俺。 笑死售躁,一個(gè)胖子當(dāng)著我的面吹牛坞淮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陪捷,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼回窘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了市袖?” 一聲冷哼從身側(cè)響起啡直,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烁涌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后酒觅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撮执,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年舷丹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抒钱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡颜凯,死狀恐怖谋币,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情症概,我是刑警寧澤蕾额,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站彼城,受9級特大地震影響诅蝶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜精肃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一秤涩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧司抱,春花似錦筐眷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至资溃,卻和暖如春武翎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背溶锭。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工宝恶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人趴捅。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓垫毙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拱绑。 傳聞我的和親對象是個(gè)殘疾皇子综芥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容