Go的100天之旅-08字串

後廠村海盜發表於2020-07-18

簡介

字串在各種程式語言中都是很基礎的一種型別,在Go中字串簡單理解就是一個陣列,陣列裡面的元素是byte型別。因此基本上擁有類似陣列的全部特性。例如len可以返回字串的位元組數,注意不是字元的長度:

s := "go"
fmt.Println(len(s)) //2

也可以根據下標訪問該位置的位元組

s := "go"
fmt.Println(s[0]) //103 字元g的ASCII碼

字串也可以類似切片的操作,取其給定範圍內的字串,生成一個新的字元

s := "hello world"
fmt.Println(s[0:5]) // "hello"

fmt.Println(s[:5]) // "hello"
fmt.Println(s[:]) // "hello world"

也可以用+操作符,把兩個字串連線成一個新的字串

s := "hello"
w := "world"

s = s + w //"hello world"

剛開始的時候我們說過,字串是不可變,這段程式碼中最後的s是一段新的字串。而不是在開始s基礎上修改的。同時先要做類似陣列那樣修改元素的值也是不可以的

s := "hello"
s[1] = 't' //編譯時會報錯

UTF-8字元

UTF-8UNICODE的一種變長度的編碼表達方式,我們都知道ASCII編碼是1個位元組,但是這也限制了它只能代表128個字元,無非對其它語言的字元進行編碼。如果把所有的字元都用統一用32位表示,的確比較簡單,但是這樣會浪費很多空間,而且歷史上的ASCII編碼的字元也無相容。UTF-8採用1-4個位元組表示字元,ASCII還是隻用1個位元組,保持相容。如果第一個位元組的是110開頭,則需要2個位元組。1110開頭則需要3個位元組,11110開頭則是4個位元組。

0xxxxxxx                             runes 0-127    (ASCII)
110xxxxx 10xxxxxx                    128-2047       (values <128 unused)
1110xxxx 10xxxxxx 10xxxxxx           2048-65535     (values <2048 unused)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx  65536-0x10ffff (other values unused)

Gostring就是採用UTF-8編碼,因此無法直接通過下標i直接訪問第i個字元,比如:

s := "你好世界"

fmt.Println(len(s)) //15

上面這段程式碼執行返回長度是12,如果想要知道有多少個字元可以利用unicode/utf8提供的功能來獲取:

package main

import (
	"fmt"
	"unicode/utf8"
)

func main() {
	s := "你好世界!"
	fmt.Println(len(s)) //15
	fmt.Println(utf8.RuneCountInString(s)) //5
}

想要分割成單個字元輸出可以通過for range:

func main() {
	s := "你好世界!"
	for i, r := range s {
		fmt.Printf("%d\t%q\t%d\n", i, r, r)
	}
}

//返回
0       '你'    20320
3       '好'    22909
6       '世'    19990
9       '界'    30028
12      '!'    65281

這次遍歷都是單個字元的遍歷,而不是單個位元組。

字串的常用操作

Go 的標準庫提供了豐富的工具,對字串進行操作,下面簡單介紹下常見的操作:

package main

import (
	"fmt"
	"strings"
)

func main() {
	s := "hello"
	fmt.Println(strings.Contains(s, "he"))         //true 是否包含子字串
	fmt.Println(strings.Replace(s, "he", "eh", 1)) // ehllo 替換第一個

        bytes := []byte(s) //轉化為byte陣列
	s2 := string(bytes)//byte陣列轉化為字串
	fmt.Println(s2)
}

字串和數字之間的轉化也是經常用到的,strconv裡面提供的豐富的功能讓它們互相轉化

import (
	"fmt"
	"strconv"
)

func main() {
	s := "123"
	i, _:= strconv.Atoi(s) //字串轉化為數字
	fmt.Println(i+2) //125

	x := 123
	var a string = strconv.Itoa(x) //數字轉化為字串
	fmt.Println(a) //123
}

如果想要動態的增加字串Go提供了Buffer型別可以動態的增加字元:

package main

import (
	"fmt"
	"bytes"
)

func main() {
	var buf bytes.Buffer
	buf.WriteString("s")

	fmt.Println(buf.String()) //s

	buf.WriteByte('A')
	fmt.Println(buf.String()) //sA
}

相關文章