1. 程式人生 > 其它 >學習筆記Go語言 4.字典、字串

學習筆記Go語言 4.字典、字串

技術標籤:go

學習筆記Go語言 4.字典、字串

4.1 字典

map是一種較為特殊的資料結構(鍵值對結構),通過給定的key可以快速獲得對應的value。

4.1.1 如何定義字典

var m1 map[string]int
m2 := make(map[int]interface{}, 100)
m3 := map[string]string{
	''name'':''james'',
	''age'':''35'',
	}

定義字典時不需要為其指定容量,因為map是可以動態增長的,但是在可以預知map容量的情況下為了提高程式的效率也最好提前標明程式的容量。需要注意的是,不能使用不能比較的元素作為字典的key,例如陣列,切片等。而value可以是任意型別的,如果使用interface{}作為value型別,那麼就可以接受各種型別的值,只不過在具體使用的時候需要使用型別斷言來判斷型別。

m3['key1']='v1' //向字典中放入元素:
len(m3)//獲取字典的長度

判斷鍵值對是否存在(value是否為空)

if value,ok := m3[''name''];ok{
	fmt.Println(value)
	}

上面這段程式碼的作用就是如果當前字典中存在key為name的字串則取出對應的value,並返回true,否則返回false。

遍歷字典:

for key,value:=range m3{
	fmt.Println('key:',key,'value:',value)
}

上面這段程式每次的輸出順序並不相同,這是因為對於一個字典來說,預設其是無序的。
(可通過切片使字典有序)

刪除字典中的值:使用go的內建函式delete

delete(m3,'key1')

將函式作為值型別存入字典:

func main(){
	m := make(map[string]func(a, b int) int)
	m["add"] = func(a, b int) int {
		return a + b
	}
	m["multi"] = func(a, b int) int {
		return a * b
	}
	fmt.Println(m["add"](3, 2))
	fmt.Println(m["multi"
](3, 2)) }

4.2 字串

4.2.1字串定義

字串是一種值型別,在建立字串之後其值是不可變的。
要修改一個字串的內容,可以將其轉換為位元組切片,再將其轉換為字串,但同樣需要重新分配記憶體。

func main(){
	s :='hello'
	b :=[]byte(s)
	b[0]='g'
	s=string(b)
	fmt.Println(s)//gello
}
len(s) //獲取字串長度

但如果字串中包含中文就不能直接使用byte切片對其進行操作,go語言中我們可以通過這種方式

func main(){
	s := "hello你好中國"
	fmt.Println(len(s)) //17
	fmt.Println(utf8.RuneCountInString(s)) //9

	b := []byte(s)
	for i := 0; i < len(b); i++ {
		fmt.Printf("%c", b[i])
	} //helloä½ å¥½ä¸­å�½
	fmt.Println()

	r := []rune(s)
	for i := 0; i < len(r); i++ {
		fmt.Printf("%c", r[i])
	} //hello你好中國
}

在go語言中字串都是以utf-8的編碼格式進行儲存的,所以每個中文佔三個位元組加上hello的5個位元組所以長度為17,如果我們通過utf8.RuneCountInString函式獲得的包含中文的字串長度則與我們的直覺相符合。而且由於中文對於每個單獨的位元組來說是不可列印的,所以可以看到很多奇怪的輸出,但是將字串轉為rune切片則沒有問題。

4.2.2 strings包

strings包提供了許多操作字串的函式。在這裡你可以看到都包含哪些函式,連結: https://golang.org/pkg/strings/.

func main() {
	var str string = "This is an example of a string"
	//判斷字串是否以Th開頭
	fmt.Printf("%t\n", strings.HasPrefix(str, "Th"))
	//判斷字串是否以aa結尾
	fmt.Printf("%t\n", strings.HasSuffix(str, "aa"))
	//判斷字串是否包含an子串
	fmt.Printf("%t\n", strings.Contains(str, "an"))
}

4.2.3 strconv包

strconv包實現了基本資料型別與字串之間的轉換。在這裡你可以看到都包含哪些函式連結: https://golang.org/pkg/strconv/.

i, err := strconv.Atoi("-42") //將字串轉為int型別
s := strconv.Itoa(-42) //將int型別轉為字串

若轉換失敗則返回對應的error值

4.2.4 字串拼接

1.Sprintf

const numbers = 100

func BenchmarkSprintf(b *testing.B) {
	b.ResetTimer()
	for idx := 0; idx < b.N; idx++ {
		var s string
		for i := 0; i < numbers; i++ {
			s = fmt.Sprintf("%v%v", s, i)
		}
	}
	b.StopTimer()
}

2.+拼接

func BenchmarkStringAdd(b *testing.B) {
	b.ResetTimer()
	for idx := 0; idx < b.N; idx++ {
		var s string
		for i := 0; i < numbers; i++ {
			s += strconv.Itoa(i)
		}
	}
	b.StopTimer()
}

3.bytes.Buffer

func BenchmarkBytesBuf(b *testing.B) {
	b.ResetTimer()
	for idx := 0; idx < b.N; idx++ {
		var buf bytes.Buffer
		for i := 0; i < numbers; i++ {
			buf.WriteString(strconv.Itoa(i))
		}
		_ = buf.String()
	}
	b.StopTimer()
}

4.strings.Builder拼接

func BenchmarkStringBuilder(b *testing.B) {
	b.ResetTimer()
	for idx := 0; idx < b.N; idx++ {
		var builder strings.Builder
		for i := 0; i < numbers; i++ {
			builder.WriteString(strconv.Itoa(i))
		}
		_ = builder.String()
	}
	b.StopTimer()
}

5.對比

BenchmarkSprintf-8         	   68277	     18431 ns/op
BenchmarkStringBuilder-8   	 1302448	       922 ns/op
BenchmarkBytesBuf-8        	  884354	      1264 ns/op
BenchmarkStringAdd-8       	  208486	      5703 ns/op