91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

golang 數據三 (字典)

發布時間:2020-03-05 04:30:07 來源:網絡 閱讀:2072 作者:100018 欄目:開發技術

golang基本數據結構Map也叫字典,字典的聲明格式如下: map[KeyType]ValueType

字典是無序鍵值對集合,字典要求KeyType必須是支持相等運算符(==,!=)的數據類型,比如:數字、字符串、指針、數組、結構體以及對應的接口類型,而ValueType可以是任意類型,字典也是引用類型,使用make函數或者初始化表達式語句來創建。比如:

{
    m := make(map[string]int)    //創建一個字典
    m["a"] = 1 
    m["b"] = 2 

    m2 := map[int]struct{   //匿名結構體
        x int 
    }{  
        1: {x:100},
        2: {x:200},
    }   
    fmt.Println(m,m2)
}


字典的基本操作

比如:

{
    m := make(map[string]int)
    m["route"] = 66 //添加key
    i := m["route"] //讀取key
    j := m["root"]  //the value type is int, so the zero value is 0
    n := len(m) //獲取長度
    //n := cap(m)   // ???  引發一個思考
    delete(m, "route") //刪除key
}

如果訪問不存在的鍵,不會引發錯誤,而會默認返回ValueType的零值,那么還能否根據零值來判斷key的存在呢?

在讀取map操作時,可以使用雙返回值來正常讀取map,比如:

{
    j, ok := m["root"]
}
說明:
ok是個bool類型變量,如果key真實存在,則ok的值為true,反之為false,如果你只是想測試key是否存在而不
獲取值的話,可以使用忽略字符"_"。

在修改map值操作時,因為受內存訪問安全和哈希算法等緣故,字典被設計成"not adrressable",因此不能直接修改value成員(結構體或數組)。比如:

{
    m := map[int] user {
        1 : {
            name:"tom",
            age:19},
    }
    m[1].age = 1        //cannot assign to struct field m[1].age in map
}

但是有兩種方式可以實現直接修改map的value成員:

  1. 是對整個value進行重新復制

  2. 聲明map時valueType為指針類型

{
    m := map[int] user {
        1 : {
            name:"tom",
            age:19},
    }
    u := m[1]
    u.age = 1
    m[1] = u
}
{
    m := map[int] *user {
        1 : {
            name:"tom",
            age:19},
    }
    m[1].age += 1
}

不能對nil字典進行寫操作,但是可以讀,比如:

{
    var m map[string]int
    //p := m["a"]       //ok
    m["a"] = 1          //panic: assignment to entry in nil map
}

map遍歷:

{
//  var m = make(map[string]int)
    var m = map[string]int{}
    m["route"] = 66
    m["root"] = 67
    for key,value := range m{
        fmt.Println("Key:", key, "Value:", value)
    }
}

因為map是無序的,如果想按照有序key輸出的話,可以先把所有的key取出,然后對key進行排序,再遍歷map,比如:

{
    m := make(map[int]int)
    var keys []int
    for i := 0 ;i <= 5;i++{
        m[i] = i
    }
                                                                                                                                                      
    for k, v := range m{
        fmt.Println("Key:",k,"Value:",v)
    }   
    for k := range m{
        keys = append(keys, k)
    }
    sort.Ints(keys)
    for _, k := range keys{
        fmt.Println("Key:",k,"Value:",m[k])
    }
}

并發

字典不是并發安全的數據結構,如果某個任務正在對字典進行寫操作,那么其他任務就不能對該字典執行并發操作(讀、寫、刪除),否則會導致程序崩潰,比如:

    m := make(map[string]int)
    go func(){
        for {
            m["a"] += 1
            time.Sleep(time.Microsecond)
        }   
    }() 

    go func (){ 
        for{
            _ = m["b"]
            time.Sleep(time.Microsecond)
        }   
    }() 
    select{}
}
輸出:
fatal error: concurrent map read and map write

GO語言編譯器提供了這種問題(競爭)的檢測方式,比如:

# go run -race file.go

安全

可以使用 sync.RWMutex 實現同步,避免并發環境多goroutings同時讀寫操作,繼續完善上面的例子,比如:

{
    var lock = new(sync.RWMutex)                                                                                                                      
    m := make(map[string]int)
    go func(){
        for {
            lock.Lock()
            m["a"]++
            lock.Unlock()
            time.Sleep(time.Microsecond)
        }   
    }() 

    go func (){ 
        for{
            lock.RLock()
            _ = m["b"]
            lock.RUnlock()
            time.Sleep(time.Microsecond)
        }   
    }() 
    select{}
}

性能

在創建字典時預先準備足夠的空間有助于提升性能,減少擴張時引發內存動態分配和重復哈希操作,比如:

package main

import "testing"
import "fmt"

func test() map[int]int {
	m := make(map[int]int)
	for i:=0; i < 1000; i++{
		m[i] = 1
	}
	return m
}

func testCap() map[int]int{
	m := make(map[int]int,1000)
	for i:=0; i < 1000; i++{
		m[i] = 1
	}
	return m
}


func BenchmarkTest(t *testing.B){
	for i:= 0;i < t.N; i++{
		test()
	}
}

func BenchmarkTestCap(t *testing.B){
	for i:= 0;i < t.N; i++{
		testCap()
	}
}

func main(){
	resTest := testing.Benchmark(BenchmarkTest)
	fmt.Printf("BenchmarkTest \t %d, %d ns/op,%d allocs/op, %d B/op\n", resTest.N, resTest.NsPerOp(), resTest.AllocsPerOp(), resTest.AllocedBytesPerOp())
	resTest = testing.Benchmark(BenchmarkTestCap)
	fmt.Printf("BenchmarkTestCap \t %d, %d ns/op,%d allocs/op, %d B/op\n", resTest.N, resTest.NsPerOp(), resTest.AllocsPerOp(), resTest.AllocedBytesPerOp())
}
輸出:
# go run conmap.go
BenchmarkTest 	 10000, 160203 ns/op,98 allocs/op, 89556 B/op
BenchmarkTestCap 20000, 65478 ns/op,12 allocs/op, 41825 B/op


借鑒:<<雨痕筆記>>

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

桐城市| 曲靖市| 胶南市| 江油市| 新沂市| 五莲县| 广宁县| 正安县| 定结县| 久治县| 德保县| 宜兴市| 松滋市| 荃湾区| 法库县| 晋宁县| 阿克陶县| 茌平县| 东乡| 庄河市| 长垣县| 信宜市| 蒲江县| 阳曲县| 巴林左旗| 东至县| 溧水县| 东丰县| 宿迁市| 平泉县| 柏乡县| 华池县| 资中县| 赤城县| 定日县| 临海市| 昌黎县| 株洲县| 桐乡市| 美姑县| 东丰县|