天天看點

golang基礎資料類型-字元串

一個字元串是一個不可改變的位元組序列,字元串可以包含任意資料,文本字元串通常被解釋為采用UTF8編碼的Unicode碼點(rune)序列

表現形式

golang中的字元串支援兩種表現形式

func TestString(t *testing.T) {
   // 形式一: 雙引号,會識别轉義字元
   str1 := "這是字元串的表現形式一。\n你可以看到換行了"

   // 形式二: 反引号,以字元串的原生形式輸出,包括換行和特殊字元,可以防止攻擊,輸出源代碼等效果
   str2 := `源代碼
func TestInt1(t *testing.T) {
   var i uint8 = 0
   i--
   fmt.Println(i) // 255
}
   `
   fmt.Println(str1)
   fmt.Println(str2)
}
           

零值

golang中的字元串是值類型,零值/預設值是空字元串""

func TestString(t *testing.T) {
   var str1 string
   fmt.Println(str1 == "") // true
}
           

長度

内置的len函數,計算的是字元串中的位元組的數量,不是字元的數量

一個中文字元可能占多個位元組數,可以使用utf8.RuneCountInString計算字元串中字元的數量

func TestString(t *testing.T) {
   // 一個中文字元可能占用多個位元組
   str := "hello,上海"
   fmt.Println(len(str))                    // 12,展示的是位元組數,不是字元數
   fmt.Println(utf8.RuneCountInString(str)) // 8,展示的是字元數
}
           

操作

索引操作s[i]傳回第i個位元組的位元組值,i必須滿足0 ≤ i< len(s)條件限制

注意:第i個位元組并不一定是字元串的第i個字元,因為對于非ASCII字元的UTF8編碼會要兩個或多個位元組

func TestString(t *testing.T) {
   // 一個中文字元可能占用多個位元組
   str := "hello,上海"

   // 索引操作s[i]傳回第i個位元組的位元組值,i必須滿足0 ≤ i< len(s)條件限制
   fmt.Println(str[0]) // 104
}
           

子字元串操作s[i:j]基于原始的s字元串的第i個位元組開始到第j個位元組(并不包含j本身)生成一個新字元串,生成的新字元串将包含j-i個位元組

不管i還是j都可能被忽略,當它們被忽略時将采用0作為開始位置,采用len(s)作為結束的位置

func TestString(t *testing.T) {
   // 一個中文字元可能占用多個位元組
   str := "hello,上海"

   // 字元串截取
   fmt.Println(str[0:5]) // hello
   // 等價于str[0:9]
   fmt.Println(str[:9])  // hello,上
  // 等價于str[6:len(str)] 
   fmt.Println(str[6:])  // 上海
}
           

字元串可以用==和<進行比較;比較通過逐個位元組比較完成的,是以比較的結果是字元串自然編碼的順序

unicode和utf8

unicode:每個符号都配置設定一個唯一的Unicode碼點,Unicode碼點對應Go語言中的rune整數類型(譯注:rune是int32等價類型)。我們可以将一個符文序清單示為一個int32序列。這種編碼方式叫UTF-32或UCS-4,每個Unicode碼點都使用同樣大小的32bit來表示。這種方式比較簡單統一,但是它會浪費很多存儲空間,因為大多數計算機可讀的文本是ASCII字元,本來每個ASCII字元隻需要8bit或1位元組就能表示

utf8:UTF8是一個将Unicode碼點編碼為位元組序列的變長編碼。UTF8編碼是由Go語言之父Ken Thompson和Rob Pike共同發明的,現在已經是Unicode的标準。UTF8編碼使用1到4個位元組來表示每個Unicode碼點,ASCII部分字元隻使用1個位元組,常用字元部分使用2或3個位元組表示

Go語言的源檔案采用UTF8編碼

周遊

如果字元串中含有中文字元,周遊的時候一定不要按照位元組周遊,一定要按照字元來周遊

func TestString(t *testing.T) {
   str := "hello,上海"

   // 方式一:直接使用range,按照字元周遊
   for i, v := range str {
      fmt.Printf("%d : %c\n", i, v)
   }

   // 方式二:轉換成rune切片,按照字元周遊
   runes := []rune(str)
   for i, v := range runes {
      fmt.Printf("%d : %c\n", i, v)
   }
}