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

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM