Golang筆記 string, byte slices, rune

我們經(jīng)常會(huì)碰到string矫钓,byte slices以及rune之間的相互轉(zhuǎn)化問(wèn)題旦万,現(xiàn)簡(jiǎn)單介紹一下莽红。

String本質(zhì)上是只讀的slice of bytes竭业。

indexing a string yields its bytes, not its characters: a string is just a bunch of bytes.

runeint32的別名,代表字符的Unicode編碼国葬,采用4個(gè)字節(jié)存儲(chǔ)贤徒,將string轉(zhuǎn)成rune就意味著任何一個(gè)字符都用4個(gè)字節(jié)來(lái)存儲(chǔ)其unicode值,這樣每次遍歷的時(shí)候返回的就是unicode值汇四,而不再是字節(jié)了接奈。

  • String is immutable byte sequence.
  • Byte slice is mutable byte sequence.
  • Rune slice is re-grouping of byte slice so that each index is a character.
 // rune is an alias for int32 and is equivalent to int32 in all ways. It is
 // used, by convention, to distinguish character values from integer values.
 type rune = int32

下面我們定義placeOfInterestraw string, 其由反引號(hào) back quotes包圍著, 因此它僅僅只能包含literal text

func main() {
    const placeOfInterest = `?`

    fmt.Printf("plain string: ")
    fmt.Printf("%s", placeOfInterest)
    fmt.Printf("\n")

    fmt.Printf("quoted string: ")
    fmt.Printf("%+q", placeOfInterest)
    fmt.Printf("\n")

    fmt.Printf("hex bytes: ")
    for i := 0; i < len(placeOfInterest); i++ {
        fmt.Printf("%x ", placeOfInterest[I])
    }
    for _, ch := range placeOfInterest {
        fmt.Printf("\nUnicode character: %c", ch)
    }
    fmt.Printf("\nThe length of placeOfInterest: %d", len(placeOfInterest))
    fmt.Printf("\n")

    const Chinese = "中國(guó)話"
    fmt.Println(len(Chinese))
    for index, runeValue := range Chinese {
          fmt.Printf("%#U starts at byte position %d\n", runeValue, index)
    }
}

輸出結(jié)果為:

plain string: ?
quoted string: "\u2318"
hex bytes: e2 8c 98
Unicode character: ?
The length of placeOfInterest: 3
9
U+4E2D '中' starts at byte position 0
U+56FD '國(guó)' starts at byte position 3
U+8BDD '話' starts at byte position 6

從上面輸出結(jié)果可以看出:

  1. 符號(hào)?的Unicode character值為U+2318船殉,其由三個(gè)字節(jié)組成:e2 8c 98。它們是UTF-8編碼表示的16進(jìn)制值2318斯嚎。
  2. 通過(guò)for range對(duì)字符串進(jìn)行遍歷時(shí)利虫,每次獲取到的對(duì)象都是rune類型的挨厚。而for循環(huán)遍歷輸出的是各個(gè)字節(jié)。
  3. go采用的是UTF-8編碼糠惫,即go的源代碼是被定義成UTF-8文本形式的疫剃,其他形式的表述是不被允許的。這就是說(shuō)硼讽,當(dāng)我們?cè)诖a中寫下?時(shí)巢价,程序?qū)⒎?hào)? 的UTF-8編碼寫入源代碼文本中。因此當(dāng)我們打印16進(jìn)制bytes時(shí)固阁,我們只是將編輯器放置在文件中的數(shù)據(jù)給dump下來(lái)了而已壤躲。
  4. 使用len函數(shù)獲取到string的長(zhǎng)度并不是字符個(gè)數(shù),而是字節(jié)個(gè)數(shù)备燃。
  5. Unicode標(biāo)準(zhǔn)使用碼點(diǎn) code point來(lái)表示a single value所表述的item碉克。例如符號(hào)?,其16進(jìn)制值為2318并齐,其code point 為U+2318漏麦。

但是由于Code point比較繞口,因此go引進(jìn)了一個(gè)新的詞匯項(xiàng)rune來(lái)表示况褪。rune經(jīng)常出現(xiàn)在library和源代碼中撕贞,它基本上就和Code point一樣,但是go語(yǔ)言將rune表示為int32的alias测垛,這樣通過(guò)一個(gè)整形值來(lái)代表Code point將更加清晰明了捏膨。因此,在Golang中我們可以將character constant稱為rune constant 赐纱。表達(dá)式'?'的類型和值分別為rune 脊奋,整形值0x2318.

需要注意的是:
Unicode 只是一個(gè)符號(hào)集,它只規(guī)定了符號(hào)的二進(jìn)制代碼疙描,卻沒(méi)有規(guī)定這個(gè)二進(jìn)制代碼應(yīng)該如何存儲(chǔ)诚隙。而UTF-8 就是在互聯(lián)網(wǎng)上使用最廣的一種 Unicode 的實(shí)現(xiàn)方式。
UTF-8 最大的一個(gè)特點(diǎn)起胰,就是它是一種變長(zhǎng)的編碼方式久又。它可以使用1~4個(gè)字節(jié)表示一個(gè)符號(hào),根據(jù)不同的符號(hào)而變化字節(jié)長(zhǎng)度效五。
UTF-8編碼格式為:

  1. 對(duì)于單字節(jié)的符號(hào)地消,字節(jié)的第一位設(shè)為0,后面7位為這個(gè)符號(hào)的 Unicode 碼畏妖。因此對(duì)于英語(yǔ)字母脉执,UTF-8 編碼和 ASCII 碼是相同的。
  2. 對(duì)于n字節(jié)的符號(hào)(n > 1)戒劫,第一個(gè)字節(jié)的前n位都設(shè)為1半夷,第n + 1位設(shè)為0婆廊,后面字節(jié)的前兩位一律設(shè)為10。剩下的沒(méi)有提及的二進(jìn)制位巫橄,全部為這個(gè)符號(hào)的 Unicode 碼淘邻。


    UTF-8編碼格式

總結(jié)

  • 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. Some people think Go strings are always UTF-8, but they are not: only string literals are UTF-8. As we showed in the previous section, string values can contain arbitrary bytes; as we showed in this one, string literals always contain UTF-8 text as long as they have no byte-level escapes. To summarize, strings can contain arbitrary bytes, but when constructed from string literals, those bytes are (almost always) UTF-8.
  • Those sequences represent Unicode code points, called runes.
  • No guarantee is made in Go that characters in strings are normalized.
  • String is a nice way to deal with short sequence, of bytes or characters. Everytime you operate on string, such as find replace string or take substring, a new string is created. This is very inefficient if string is huge, such as file content. [see Golang: String]
  • Byte slice is just like string, but mutable. i.e. you can modify each byte or character. This is very efficient for working with file content, either as text file, binary file, or IO stream from networking. [see Golang: Slice]
  • Rune slice is like byte slice, except that each index is a character instead of a byte. This is best if you work with text files that have lots non-ASCII characters, such as Chinese text or math formulas ∑ or text with emoji ? . [see Golang: Rune]

References

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市彩倚,隨后出現(xiàn)的幾起案子筹我,更是在濱河造成了極大的恐慌,老刑警劉巖署恍,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崎溃,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡盯质,警方通過(guò)查閱死者的電腦和手機(jī)袁串,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)呼巷,“玉大人囱修,你說(shuō)我怎么就攤上這事⊥鹾罚” “怎么了破镰?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)压储。 經(jīng)常有香客問(wèn)我鲜漩,道長(zhǎng),這世上最難降的妖魔是什么集惋? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任孕似,我火速辦了婚禮,結(jié)果婚禮上刮刑,老公的妹妹穿的比我還像新娘喉祭。我一直安慰自己,他們只是感情好雷绢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布泛烙。 她就那樣靜靜地躺著,像睡著了一般翘紊。 火紅的嫁衣襯著肌膚如雪蔽氨。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音鹉究,去河邊找鬼中捆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛坊饶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播殴蓬,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼匿级,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了染厅?” 一聲冷哼從身側(cè)響起痘绎,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肖粮,沒(méi)想到半個(gè)月后孤页,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涩馆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年行施,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片魂那。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蛾号,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涯雅,到底是詐尸還是另有隱情鲜结,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布活逆,位于F島的核電站精刷,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蔗候。R本人自食惡果不足惜怒允,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望琴庵。 院中可真熱鬧误算,春花似錦、人聲如沸迷殿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)庆寺。三九已至蚊夫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間懦尝,已是汗流浹背知纷。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工壤圃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人琅轧。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓伍绳,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親乍桂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冲杀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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