成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go語言Map拷貝陷阱、Slice更新陷阱

開發
map 其實是不能拷貝的,如果想要拷貝一個 map ,只有一種辦法就是循環賦值,就像這樣,如果 map 中有指針,還要考慮深拷貝的過程。

 [[410263]]

map 可以拷貝嗎?

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

  1. originalMap := make(map[string]int
  2. originalMap["one"] = 1 
  3. originalMap["two"] = 2 
  4.  
  5. // Create the target map 
  6. targetMap := make(map[string]int
  7.  
  8. // Copy from the original map to the target map 
  9. for key, value := range originalMap { 
  10.     targetMap[key] = value 

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

  1. originalMap := make(map[string]*int
  2. var num int = 1 
  3. originalMap["one"] = &num 
  4.  
  5. // Create the target map 
  6. targetMap := make(map[string]*int
  7.  
  8. // Copy from the original map to the target map 
  9. for key, value := range originalMap { 
  10. var tmpNum int = *value 
  11.     targetMap[key] = &tmpNum 

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

  1. map["one"] = 1 

但如果 value 是一個結構體,可以直接替換結構體,但無法更新結構體內部的值

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

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

  • Cannot assign to originalMap["minibear2333"].age”

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

簡單來說就是map不是一個并發安全的結構,所以,并不能修改他在結構體中的值。

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

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

因為懶得該這個結構體,就選擇了方法2

要么創建個臨時變量,做拷貝,像這樣

  1. tmp := m["foo"
  2. tmp.x = 4 
  3. m["foo"] = tmp 

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

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

slice復制陷阱

切片有一種方式復制方式,比較快速

  1. slice3 :=  slice2[:] 

但是有一種致命的缺點,這是淺拷貝,slice3和slice2是同一個切片,無論改動哪個,另一個都會產生變化。

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

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

我們在讀入讀出輸入流的時候,極易出現這樣的問題

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

  1. buffer := bytes.NewBuffer(make([]byte, 0, 100)) 
  2. buffer.Write([]byte("abc")) 
  3. resBytes := buffer.Bytes() 
  4. fmt.Printf("%s \n", resBytes) 
  5. resBytes[0] = 'd' 
  6. fmt.Printf("%s \n", resBytes) 
  7. fmt.Printf("%s \n", buffer.Bytes()) 

輸出,可以看出會影響到原切片內容

  1. abc 
  2. dbc 
  3. dbc 

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

腳注

直接點擊閱讀原文跳轉

  • 試下源碼函數 updateMapValue:https://github.com/golang-minibear2333/golang/blob/master/2.func-containers/2.4-map/map1.go#L89
  • issue-3117:https://github.com/golang/go/issues/3117
  • ianlancetaylor:https://github.com/golang/go/issues/3117#issuecomment-430632750
  • 源碼 https://github.com/golang/go/blob/cb4cd9e17753b5cd8ee4cd5b1f23d46241b485f1/src/bytes/buffer.go#L54

本文轉載自微信公眾號「機智的程序員小熊」,可以通過以下二維碼關注。轉載本文請聯系機智的程序員小熊公眾號。

 

責任編輯:武曉燕 來源: 機智的程序員小熊
相關推薦

2023-06-26 00:03:55

Go語言類型

2023-07-03 00:44:26

Go語言MySQL

2012-06-15 09:56:40

2024-01-07 23:11:16

defer?Go語言

2025-06-04 02:15:55

Go語言Slice

2023-12-04 18:31:59

C語言函數

2022-02-09 16:02:26

Go 語言ArraySlice

2014-07-29 09:16:14

Fragment

2025-04-27 09:45:58

JavaScript深拷貝淺拷貝

2010-07-14 17:03:52

編程語言

2010-07-19 15:49:22

求職陷阱

2010-10-27 11:04:01

招聘

2010-07-28 13:31:10

Flex數據綁定

2024-04-29 14:39:20

2022-10-14 09:12:59

參數Python類型

2024-06-12 08:54:49

Go切片參數

2011-07-14 10:23:33

C語言

2021-03-01 15:52:14

開源開源軟件陷阱

2018-06-11 15:26:47

云計算企業云陷阱

2021-04-22 11:22:12

云計算數據遷移混合云
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久国产一区二区 | 精品国产伦一区二区三区观看说明 | 中文字幕成人av | 午夜影院在线观看 | 国产亚洲精品综合一区 | 欧美午夜一区 | 中文字幕一区二区三区不卡 | 久久久久1 | 伊人免费观看视频 | 欧美一区二区三区久久精品 | 2018天天干天天操 | 亚洲电影第1页 | 免费视频二区 | 精品美女 | 午夜看电影在线观看 | 亚洲大片在线观看 | 国产精品视频免费播放 | 天堂中文在线观看 | 久久久久亚洲 | 婷婷中文在线 | 伊人手机在线视频 | 神马久久春色视频 | 一区二区三区视频播放 | 国产成人精品久久二区二区91 | 亚洲在线一区 | 一级a爱片性色毛片免费 | 黑人巨大精品欧美一区二区免费 | 羞羞在线观看视频 | 欧美成人a | 欧美日韩高清 | 亚洲网在线| 狠狠色网 | 中文字幕av亚洲精品一部二部 | 欧美精品久久久久 | 四虎影院在线观看免费视频 | 在线亚洲免费视频 | 老牛影视av一区二区在线观看 | 国产在线高清 | 国产精品96久久久久久 | 久久青草av | 中文字幕一区二区三区精彩视频 |