Go語言中的字符和字符串


Go語言中的字符

在Go語言中,沒有字符類型,字符類型是rune類型,rune是int32的別稱。

下面用一個簡單的程序來演示字符類型:

package main

import (
    "fmt"
    "reflect"
)

func main() {
    r := '我'
    fmt.Printf("%q的類型為:%t 二進制為:%b\n", r, r, r)

    rType := reflect.TypeOf(r).Kind()
    fmt.Printf("r的實際類型為:%s\n", rType)
}

程序輸出:

'我'的類型為:%!t(int32=25105) 二進制為:110001000010001
r的實際類型為:int32

Go語言天生支持Unicode,那我產生一個問題:Unicode字符的長度是多少?
這個問題的問法有沒有問題?其實仔細想想,這樣問是有問題的。首先,Unicode的基礎是一個有編號的字符集,在字符集之上又規定了模塊化的編碼等等技術層次,各種具體的編碼形式並不一致。因此,嚴格來說,Unicode是沒有“長度”這一說的,它是抽象的字符,只有Unicode的編碼才有具體的字節長度。而且不同的編碼實現,長度也不一樣。

Unicode 目前規划的總空間是17個平面(平面0至16),每個平面有 65536 個碼點。我們常用的平面0(「Basic Multilingual Plane」,即「BMP」)碼點范圍為0x0000 至 0xFFFF,這並不是 Unicode 的全部。

BMP 的字符是 Unicode 中最基礎和最常用的一部分,以 UTF-16 編碼時使用2字節,以 UTF-8編碼時使用1至3字節。超出 BMP 的字符以 UTF-16 或 UTF-8 編碼都需要4字節。另外還有一個比較少用的編碼形式,UTF-32,它編碼任何 Unicode 字符都需要4個字節。

Go語言中的字符串

Go語言的字符串有兩種方式來表示:

  • 雙引號,可以使用轉義字符,如s := "Go語言字符串\n不能跨行賦值"
  • 反引號,字符串跟反引號中的格式一樣,即Raw Type
s := `Go原格式字符串
    可以跨行`

Go語言的字符串是以UTF-8格式編碼並存儲的,下面有一個簡單的例子:

package main

import (
    "fmt"
)

func main() {
    s := "我"
    fmt.Printf("s的類型為:%t, 長度為:%d, 16進制為:%x\n", s, len(s), s)

    for i, b := range []byte(s) {
        fmt.Printf("第%d個字節為:%b\n", i, b)
    }
}

程序輸出:

s的類型為:%!t(string=我), 長度為:3, 16進制為:e68891
第0個字節為:11100110
第1個字節為:10001000
第2個字節為:10010001

變量s中存放的是這個字符串的UTF-8編碼,當你使用len(s)函數獲取字符串的長度時,獲取的是該字符串的UTF-8編碼長度,存儲一個字符可能需要 2個、3個或者4個字節,它是不固定的。

UTF-8的編碼遵循如下2條規則:

  • 對於單字節的符號,字節的第一位設為0,后面7位為這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
  • 對於n字節的符號(n>1),第一個字節的前n位都設為1,第n+1位設為0,后面字節的前兩位一律設為10。剩下的沒有提及的二進制位,全部為這個符號的unicode碼。

根據這兩條簡單的規則,我們可以把UTF-8編碼轉換為Unicode的碼點:

//utf8轉為unicode
          1110 0110 1000 1000 1001 0001 // s
               0110   00 1000   01 0001 // s utf8 -> unicode
          0000 0000 0110 0010 0001 0001 // s utf8 -> unicode
0000 0000 0000 0000 0110 0010 0001 0001 // r

我們可以看到上面推導的結果跟程序的輸出結果相符。

參考


免責聲明!

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



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