1. 程式人生 > >Go 的 rune byte 和 string

Go 的 rune byte 和 string

  • runebytestring 都是 Go 的內建型別

  • byte
    • byte是uint8的別名,在所有方面都等同於uint8
    • 按慣例,它用於區分位元組值8位無符號整數值
  • rune
    • runeint32的別名,在所有方面都等同於int32
    • 按慣例,它用於區分字元值整數值
  • string
    • string是所有8位位元組字串的集合,通常但不一定代表UTF-8編碼的文字
    • 字串可能為空,但是不能為 nil
    • 字串型別的值是不可變的
  • 由上面得解釋我們大概可以明白
    • rune 可以表示得比 byte
    • string 型別的底層是一個byte 陣列
    • 以上解釋都來此 Go 原始碼註釋

  • 剛剛上面標註了位元組字元,現在我們來梳理字元和位元組的概念

  • 儲存單位 位元組

    • 計算機儲存資訊的最小單位,稱之為 bit,二進位制的一個01叫一位
    • 計算機儲存容量基本單位是位元組 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 世界!,這證明 GoUTF-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 的操作單位是一個字元,不管這個字元是什麼字元