1、range關鍵字
Go語言有個特殊的關鍵字 range,它可以配合關鍵字 for 來迭代切片里的元素。注意,range 創建了每個元素的副本,而不是直接返回對該元素的引用。
示例:
package main import "fmt" func main() { arr := []int{1,2,3} for i,v := range arr { fmt.Printf("%p, %p, %p\n", &i, &v, &arr[i]) } }
2、map
Go語言中 map 是一種特殊的數據結構,一種元素對(pair)的無序集合,pair 對應一個 key(索引)和一個 value(值),所以這個結構也稱為關聯數組或字典,這是一種能夠快速尋找值的理想結構,給定 key,就可以迅速找到對應的 value。
1)聲明
map 是引用類型,可以使用如下方式聲明:
var mapname map[keytype]valuetype
其中,mapname 為 map 的變量名,keytype 為鍵類型,valuetype 是鍵對應的值類型。
未初始化的 map 的值是 nil。
注意:可以使用 make(),但不能使用 new() 來構造 map,如果錯誤的使用 new() 分配了一個引用對象,會獲得一個空引用的指針,相當於聲明了一個未初始化的變量並且取了它的地址 。
示例:
package main import "fmt" func main() { var kv map[string]int kv = make(map[string]int) // 使用前需要先初始化 kv["A"] = 1 kv["B"] = 2 fmt.Println(kv) }
2)遍歷
map 的遍歷過程使用 for range 循環完成。
3)元素的刪除與清空
使用 delete() 內建函數從 map 中刪除一組鍵值對,delete() 函數的格式如下:
delete(map, 鍵)
Go語言中並沒有為 map 提供任何清空所有元素的函數、方法,清空 map 的唯一辦法就是重新 make 一個新的 map。
示例:
package main import "fmt" func main() { kv := map[string]int{} kv["A"] = 1 kv["B"] = 2 kv["C"] = 3 delete(kv, "A") fmt.Println(kv) }
3、sync.Map
Go語言在 1.9 版本中提供了一種效率較高的並發安全的 sync.Map,sync.Map 和 map 不同,不是以語言原生形態提供,而是在 sync 包下的特殊結構。
sync.Map 有以下特性:
- 無須初始化,直接聲明即可。
- sync.Map 不能使用 map 的方式進行取值和設置等操作,而是使用 sync.Map 的方法進行調用,Store 表示存儲,Load 表示獲取,Delete 表示刪除。
- 使用 Range 配合一個回調函數進行遍歷操作,通過回調函數返回內部遍歷出來的值,Range 參數中回調函數的返回值在需要繼續迭代遍歷時,返回 true,終止迭代遍歷時,返回 false。
示例:
package main import ( "fmt" "sync" ) func main() { var mp = sync.Map{} mp.Store("A", 1) mp.Store("B", 2) mp.Store("C", 3) fmt.Println(mp.Load("A")) // 取值 mp.Delete("A") // 刪值 mp.Range(func(key, value interface{}) bool { // 遍歷 fmt.Println("iterate:", key, value) return true }) }
4、list
在Go語言中,列表使用 container/list 包來實現,內部的實現原理是雙鏈表,列表能夠高效地進行任意位置的元素插入和刪除操作。
1)初始化
list 的初始化有兩種方法:分別是使用 New() 函數和 var 關鍵字聲明,兩種方法的初始化效果都是一致的。
通過 container/list 包的 New() 函數初始化 list:變量名 := list.New()
通過 var 關鍵字聲明初始化 list :var 變量名 list.List
列表與切片和 map 不同的是,列表並沒有具體元素類型的限制,因此,列表的元素可以是任意類型。
2)插入元素
雙鏈表支持從隊列前方或后方插入元素,分別對應的方法是 PushFront 和 PushBack。
其他插入方法:
InsertAfter(v interface {}, mark * Element) * Element——在 mark 點之后插入元素
InsertBefore(v interface {}, mark * Element) *Element——在 mark 點之前插入元素
PushBackList(other *List)——添加 other 列表元素到尾部
PushFrontList(other *List)——添加 other 列表元素到頭部
3)刪除元素
列表插入函數的返回值會提供一個 *list.Element 結構,這個結構記錄着列表元素的值以及與其他節點之間的關系等信息,從列表中刪除元素時,需要用到這個結構進行快速刪除。
4)遍歷
遍歷雙鏈表需要配合 Front() 函數獲取頭元素,遍歷時只要元素不為空就可以繼續進行,每一次遍歷都會調用元素的 Next() 函數。
示例:
package main import ( "container/list" "fmt" ) func main() { l := list.New() l.PushBack("B") l.PushFront("A") ele := l.PushBack("C") l.InsertAfter("After", ele) l.InsertBefore("Before", ele) l.Remove(ele) // 刪除元素 for i:=l.Front(); i != nil; i = i.Next(){ fmt.Println(i.Value) } }