<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          go語言map拷貝陷阱、slice更新陷阱

          共 2985字,需瀏覽 6分鐘

           ·

          2021-07-14 01:57

          開源電子書 https://golang.coding3min.com

          map 可以拷貝嗎?

          map 其實是不能拷貝的,如果想要拷貝一個 map ,只有一種辦法就是循環(huán)賦值,就像這樣

          originalMap := make(map[string]int)
          originalMap["one"] = 1
          originalMap["two"] = 2

          // Create the target map
          targetMap := make(map[string]int)

          // Copy from the original map to the target map
          for key, value := range originalMap {
              targetMap[key] = value
          }

          如果 map 中有指針,還要考慮深拷貝的過程

          originalMap := make(map[string]*int)
          var num int = 1
          originalMap["one"] = &num

          // Create the target map
          targetMap := make(map[string]*int)

          // Copy from the original map to the target map
          for key, value := range originalMap {
          var tmpNum int = *value
              targetMap[key] = &tmpNum
          }

          如果想要更新 map 中的value,可以通過賦值來進行操作

          map["one"] = 1

          但如果 value 是一個結(jié)構(gòu)體,可以直接替換結(jié)構(gòu)體,但無法更新結(jié)構(gòu)體內(nèi)部的值

          originalMap := make(map[string]Person)
          originalMap["minibear2333"] = Person{age: 26}
          originalMap["minibear2333"].age = 5

          你可以 試下源碼函數(shù)[腳注1] 會報這個錯誤

          Cannot assign to originalMap["minibear2333"].age

          問題鏈接 issue-3117[腳注2] , 其中 ianlancetaylor[腳注3] 的回答很好的解釋了這一點

          簡單來說就是map不是一個并發(fā)安全的結(jié)構(gòu),所以,并不能修改他在結(jié)構(gòu)體中的值。

          這如果目前的形式不能修改的話,就面臨兩種選擇,

          • 1.修改原來的設(shè)計;
          • 2.想辦法讓map中的成員變量可以修改,

          因為懶得該這個結(jié)構(gòu)體,就選擇了方法2

          要么創(chuàng)建個臨時變量,做拷貝,像這樣

          tmp := m["foo"]
          tmp.x = 4
          m["foo"] = tmp

          要么直接用指針,比較方便

          originalPointMap := make(map[string]*Person)
          originalPointMap["minibear2333"] = &Person{age: 26}
          originalPointMap["minibear2333"].age = 5

          slice復(fù)制陷阱

          切片有一種方式復(fù)制方式,比較快速

           slice3 :=  slice2[:]

          但是有一種致命的缺點,這是淺拷貝,slice3slice2是同一個切片,無論改動哪個,另一個都會產(chǎn)生變化。

          可能這么說你還是不能加深理解。在源碼bytes.buffer[腳注4]中出現(xiàn)了這一段

          func (b *Buffer) Bytes() []byte {
              return b.buf[b.off:] 
          }

          我們在讀入讀出輸入流的時候,極易出現(xiàn)這樣的問題

          下面的例子,使用abc模擬讀入內(nèi)容,修改返回值內(nèi)容

           buffer := bytes.NewBuffer(make([]byte0100))
           buffer.Write([]byte("abc"))
           resBytes := buffer.Bytes()
           fmt.Printf("%s \n", resBytes)
           resBytes[0] = 'd'
           fmt.Printf("%s \n", resBytes)
           fmt.Printf("%s \n", buffer.Bytes())

          輸出,可以看出會影響到原切片內(nèi)容

          abc
          dbc
          dbc

          這種情況在并發(fā)使用的時候尤為危險,特別是流式讀寫的時候容易出現(xiàn)上一次沒處理完成,下一次的數(shù)據(jù)覆蓋寫入的錯亂情況

          腳注

          直接點擊閱讀原文跳轉(zhuǎn)

          1. 試下源碼函數(shù) updateMapValue:https://github.com/golang-minibear2333/golang/blob/master/2.func-containers/2.4-map/map1.go#L89
          2. issue-3117:https://github.com/golang/go/issues/3117
          3. ianlancetaylor:https://github.com/golang/go/issues/3117#issuecomment-430632750
          4. 源碼 https://github.com/golang/go/blob/cb4cd9e17753b5cd8ee4cd5b1f23d46241b485f1/src/bytes/buffer.go#L54
          go語言交流群已開放,搜索qupzhi加我微信拉群
          瀏覽 71
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91香蕉| 婷婷五月天激情综合网 | 亚洲人性爱视频 | 日本三级电影片一区二区 | 我要看一级黄色视频 |