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) } }