Golang之情非得已的DeepCopy

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

續日今天問我:Golang裡面如果做結構體的深拷貝呢?他說他的excelize庫被網友爆出一個Bug:

改變sheet2頁上的資料,sheet1上的資料會一起發生變化,最後他定位到問題是由於自己做了兩個sheet結構體的淺拷貝導致的。因為sheet對應的結構體的特殊性其必須是指標類型。是啊。。。這樣就坑了,Golang裡面怎麼做一個超級無敵複雜結構體的指標變數的深拷貝呢?給個例子:

type KDeepCopy struct {    A map[string]string    B []string    C struct {        D [][]string        E map[interface{}]F        G string        K func()    }}type F struct {    K map[int]*string}

var k *KDeepCopy = &KDeepCopy{....} , var h *KDeepCopy。 這個時候想把k這個變數的記憶體中的值全部深拷貝到h這個變數上,即k和h指向不同記憶體地區。C++裡面我們可以使用memcpy函數(或者類似的函數)來完成。但Golang官方沒有提供這樣的API函數給我們直接操作記憶體。這裡給出一個解決方案(續神提供的),我寫了簡單的demo代碼驗證。demo中給了json和gob兩種方法去解決,這兩種編解碼方案哪種更好,自己評鑒。

package mainimport (    "bytes"    "encoding/gob"    "encoding/json"    "fmt")type GDeepCopy struct {    A map[string]string    B []string    D int}type DeepCopy struct {    A map[string]string    B []string    C Cc}type Cc struct {    D map[int]*string}func main() {    var cc Cc = Cc{        D: make(map[int]*string, 0),    }    var dc DeepCopy = DeepCopy{        A: make(map[string]string, 0),        B: []string{`b`, `c`, `d`},        C: cc,    }    dv := DeepCopy{}    dv = dc    fmt.Printf("dc : %p\n", &dc)    fmt.Printf("dv: %p\n", &dv)    dv.B = []string{`f`, `g`, `d`}    fmt.Println(`dc:`, dc)    fmt.Println(`dv:`, dv)    fmt.Println(`=============================`)    var df *DeepCopy = &DeepCopy{        A: make(map[string]string, 0),        B: []string{`b`, `c`, `d`},        C: cc,    }    dn := &DeepCopy{}    dn = df    fmt.Printf("dn : %p\n", dn)    fmt.Printf("df: %p\n", df)    dn.B = []string{`f`, `g`, `d`}    fmt.Println(`df:`, df)    fmt.Println(`dn:`, dn)    fmt.Println(`=============================`)    var buf bytes.Buffer    dg := &DeepCopy{}    json.NewEncoder(&buf).Encode(*df)    json.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dg)    dg.B = []string{`h`, `j`, `k`}    fmt.Printf("df : %p\n", df)    fmt.Printf("dg: %p\n", dg)    fmt.Println(`df:`, df)    fmt.Println(`dg:`, dg)    fmt.Println(`=============================`)    dj := &GDeepCopy{}    gob.NewEncoder(&buf).Encode(*df)    gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dj)    dj.B = []string{`q`, `w`, `e`}    fmt.Printf("df : %p\n", df)    fmt.Printf("dj: %p\n", dj)    fmt.Println(`df:`, df)    fmt.Println(`dj:`, dj)    fmt.Println(`=============================`)}

是的,可以通過先把struct序列化儲存到一個buffer裡面,然後將buffer裡面的Byte()資料進行還原序列化到執行對象裡面即可。是不是感覺好麻煩呢?如果你有什麼好的方案,請在評論區貼出。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.