range关键字,map,sync.Map,list

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

  

猜你喜欢

转载自www.cnblogs.com/ACGame/p/11876798.html