1. 程式人生 > >go語言---map

go語言---map

field 傳引用 塊存儲 === 聲明 print ann 維護 ava

go語言---map

https://blog.csdn.net/cyk2396/article/details/78890185

一.map的用法:

type PersonDB struct {
    Id      string
    Name    string
    Address string
}

fmt.Println("=========Map===========")
    //map是一堆鍵值對的未排序集合,在golang中是內置類型,可以直接使用,不像Java需要引入HashMap
    var personMap map[string]PersonDB                                 //聲明一個map變量,string是鍵的類型,PersonDB是值的類型
    personMap = make(map[string]PersonDB, 10)                         //創建一個map,初始容量為10
    personMap["1"] = PersonDB{Id: "1", Name: "zs", Address: "北京市房山區"} //給map元素賦值
    personMap["2"] = PersonDB{Id: "2", Name: "ls", Address: "北京市海澱區"}
    //使用內置函數delete刪除personMap中key="1"的元素,如果找不到該key,則什麽也不會發生,如果personMap為nil,則拋錯
    delete(personMap, "1")
    if value, ok := personMap["2"]; ok { //找到key=2的元素,則ok=true,value為找到的值;否則ok=false
        fmt.Println(value)
    }

    personMap2 := map[string]PersonDB{"3": PersonDB{"3", "ww", "杭州市西湖區"}} //創建並初始化一個map
    personMap2["4"] = PersonDB{"4", "ll", "北京市東城區"}
    for k, v := range personMap2 { //使用range遍歷map中的元素
        fmt.Println(k, v)
        if k == "3" {
            v.Name = "wwUpdate"
            personMap2["3"] = v //可更改value值
            //以下這種賦值方式會報錯,只能對value賦值,不能直接更改其成員變量
            // personMap2["3"].Name = "wwUpdate" //cannot assign to struct field personMap2["3"].Name in map
        }
    }
    fmt.Println(personMap2)

    

輸出結果:
fatal error: concurrent map writes
由結果可知:map不是線程安全的。
至於為什麽不是線程安全,以後再分析

三.map傳值還是傳引用?

運行以下代碼:

//map傳值還是傳引用? map和slice,channel一樣,內部都有一個指向真正存儲空間的指針,所以,即使傳參時是對值的復制(傳值),但都指向同一塊存儲空間。
    var myMapV map[string]int
    var myMap1 map[string]int
    myMapV = map[string]int{"value": 0}
    myMap1 = myMapV
    fmt.Println("m =", myMapV)
    fmt.Println("m1 =", myMap1)
    myMap1["value"] = 1
    fmt.Println("m =", myMapV)
    fmt.Println("m1 =", myMap1)

二.map是線程安全的嗎?

運行以下代碼:


//map不是線程安全的。
     cMap := make(map[string]int)
    for i := 0; i < 100; i++ {
        go func() {
            for j := 0; j < 100; j++ {
            cMap[fmt.Sprintf("%d", j)] = j //fatal error: concurrent map writes
            }
        }()
    }
     time.Sleep(3 * time.Second)

輸出結果:
m = map[value:0]
m1 = map[value:0]
m = map[value:1]
m1 = map[value:1]
我們發現,當修改了m1,m也隨著改變了,這看似是傳引用,但其實map也是傳值的,它的原理和數組切片類似。map內部維護著一個指針,該指針指向真正的map存儲空間。我們可以將map描述為如下結構:

type map[key]value struct{
impl *Map_K_V
}
type Map_K_V struct{
//......
}
其實,map和slice,channel一樣,內部都有一個指向真正存儲空間的指針,所以,即使傳參時是對值的復制(傳值),但都指向同一塊存儲空間。

go語言---map