自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go語(yǔ)言Map拷貝陷阱、Slice更新陷阱

開發(fā)
map 其實(shí)是不能拷貝的,如果想要拷貝一個(gè) map ,只有一種辦法就是循環(huán)賦值,就像這樣,如果 map 中有指針,還要考慮深拷貝的過(guò)程。

 [[410263]]

map 可以拷貝嗎?

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

  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 中有指針,還要考慮深拷貝的過(guò)程

  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,可以通過(guò)賦值來(lái)進(jìn)行操作

  1. map["one"] = 1 

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

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

你可以 試下源碼函數(shù)[腳注1] 會(huì)報(bào)這個(gè)錯(cuò)誤

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

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

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

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

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

因?yàn)閼械迷撨@個(gè)結(jié)構(gòu)體,就選擇了方法2

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

  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復(fù)制陷阱

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

  1. slice3 :=  slice2[:] 

但是有一種致命的缺點(diǎn),這是淺拷貝,slice3和slice2是同一個(gè)切片,無(wú)論改動(dòng)哪個(gè),另一個(gè)都會(huì)產(chǎn)生變化。

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

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

我們?cè)谧x入讀出輸入流的時(shí)候,極易出現(xiàn)這樣的問題

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

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

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

  1. abc 
  2. dbc 
  3. dbc 

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

腳注

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

  • 試下源碼函數(shù) 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

本文轉(zhuǎn)載自微信公眾號(hào)「機(jī)智的程序員小熊」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系機(jī)智的程序員小熊公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 機(jī)智的程序員小熊
相關(guān)推薦

2023-06-26 00:03:55

Go語(yǔ)言類型

2023-07-03 00:44:26

Go語(yǔ)言MySQL

2024-01-07 23:11:16

defer?Go語(yǔ)言

2012-06-15 09:56:40

2023-12-04 18:31:59

C語(yǔ)言函數(shù)

2025-04-27 09:45:58

JavaScript深拷貝淺拷貝

2022-02-09 16:02:26

Go 語(yǔ)言ArraySlice

2014-07-29 09:16:14

Fragment

2010-07-14 17:03:52

編程語(yǔ)言

2022-10-14 09:12:59

參數(shù)Python類型

2024-06-12 08:54:49

Go切片參數(shù)

2010-10-27 11:04:01

招聘

2010-07-28 13:31:10

Flex數(shù)據(jù)綁定

2010-07-19 15:49:22

求職陷阱

2024-04-29 14:39:20

2021-03-01 15:52:14

開源開源軟件陷阱

2011-07-14 10:23:33

C語(yǔ)言

2024-09-03 09:45:36

2022-07-28 12:17:36

C語(yǔ)言typedef#define

2023-05-09 07:09:02

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)