偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

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

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

  1. map["one"] = 1 

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

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

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

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

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

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

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

  • 1.修改原來的設(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è)切片,無論改動哪個(gè),另一個(gè)都會產(chǎn)生變化。

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

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

我們在讀入讀出輸入流的時(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()) 

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

  1. abc 
  2. dbc 
  3. dbc 

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

腳注

直接點(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)載自微信公眾號「機(jī)智的程序員小熊」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系機(jī)智的程序員小熊公眾號。

 

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

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語言函數(shù)

2022-02-09 16:02:26

Go 語言ArraySlice

2025-04-27 09:45:58

JavaScript深拷貝淺拷貝

2014-07-29 09:16:14

Fragment

2010-07-14 17:03:52

編程語言

2022-10-14 09:12:59

參數(shù)Python類型

2010-07-19 15:49:22

求職陷阱

2010-10-27 11:04:01

招聘

2010-07-28 13:31:10

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

2024-04-29 14:39:20

2024-06-12 08:54:49

Go切片參數(shù)

2011-07-14 10:23:33

C語言

2021-03-01 15:52:14

開源開源軟件陷阱

2018-06-11 15:26:47

云計(jì)算企業(yè)云陷阱

2021-04-22 11:22:12

云計(jì)算數(shù)據(jù)遷移混合云
點(diǎn)贊
收藏

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