Go語(yǔ)言關(guān)于幾種深度拷貝(deepcopy)方法的性能對(duì)比
幾種深度拷貝(deepcopy)方法性能對(duì)比
Go語(yǔ)言中所有賦值操作都是值傳遞,如果結(jié)構(gòu)中不含指針,則直接賦值就是深度拷貝;如果結(jié)構(gòu)中含有指針(包括自定義指針,以及切片,map等使用了指針的內(nèi)置類型),則數(shù)據(jù)源和拷貝之間對(duì)應(yīng)指針會(huì)共同指向同一塊內(nèi)存,這時(shí)深度拷貝需要特別處理。
目前有三種方法
- 一是用gob序列化成字節(jié)序列再反序列化生成克隆對(duì)象
- 二是先轉(zhuǎn)換成json字節(jié)序列,再解析字節(jié)序列生成克隆對(duì)象
- 三是針對(duì)具體情況,定制化拷貝
前兩種方法雖然比較通用但是因?yàn)槭褂昧藃eflex反射,性能比定制化拷貝要低出2個(gè)數(shù)量級(jí),所以在性能要求較高的情況下應(yīng)該盡量避免使用前兩者。
結(jié)論數(shù)據(jù)
執(zhí)行一次的時(shí)間
gob time:454µs
json time:170µs
custom time:2µs
測(cè)試代碼如下:
package main import ( "bytes" "encoding/gob" "encoding/json" "fmt" "time" ) type AuthorInfo struct { Name string `json:name` Age int `json:age` Country *int `json:country` } type Book struct { Title string `json:title` Author AuthorInfo `json:author` Year int `json:year` Category []string `json:category` Price map[string]string `json:price` } func DeepCopyByGob(dst, src interface{}) error { var buffer bytes.Buffer if err := gob.NewEncoder(&buffer).Encode(src); err != nil { return err } return gob.NewDecoder(&buffer).Decode(dst) } func DeepCopyByJson(src []Book) (*[]Book, error) { var dst = new([]Book) b, err := json.Marshal(src) if err != nil { return nil, err } err = json.Unmarshal(b, dst) return dst, err } func DeepCopyByCustom(src []Book) []Book { dst := make([]Book, len(src)) for i, book := range src { tmpbook := Book{} tmpbook.Title = book.Title tmpbook.Year = book.Year tmpbook.Author = AuthorInfo{} tmpbook.Author.Name = book.Author.Name tmpbook.Author.Age = book.Author.Age tmpbook.Author.Country = new(int) *tmpbook.Author.Country = *book.Author.Country tmpbook.Category = make([]string, len(book.Category)) for index, category := range book.Category { tmpbook.Category[index] = category } tmpbook.Price = make(map[string]string) for k, v := range book.Price { tmpbook.Price[k] = v } dst[i] = tmpbook } return dst } func check(err error){ if err != nil{ panic(err) } } func print(name string, books []Book){ for index,book := range books{ fmt.Printf("%s[%d]=%v country=%d\n", name, index, book, *book.Author.Country) } } func main() { //初始化源Book切片 books := make([]Book, 1) country := 1156 author := AuthorInfo{"David", 38, &country} price := make(map[string]string) price["Europe"] = "$56" books[0] = Book{"Tutorial", author, 2020, []string{"math", "art"}, price} print("books",books) var err error var start time.Time //Gob拷貝 start = time.Now() booksCpy := make([]Book, 1) err = DeepCopyByGob(&booksCpy, books) fmt.Printf("\ngob time:%v\n", time.Now().Sub(start)) check(err) *booksCpy[0].Author.Country = 1134 booksCpy[0].Category[0] = "literature" booksCpy[0].Price["America"] = "$250" print("booksCpy",booksCpy) print("books",books) //JSON拷貝 start = time.Now() booksCpy2, err_json := DeepCopyByJson(books) fmt.Printf("\njson time:%v\n", time.Now().Sub(start)) check(err_json) *(*booksCpy2)[0].Author.Country = 1135 (*booksCpy2)[0].Category[0] = "science" (*booksCpy2)[0].Price["Canada"] = "$150" print("(*booksCpy2)",*booksCpy2) print("books",books) //定制拷貝 start = time.Now() booksCpy3 := DeepCopyByCustom(books) fmt.Printf("\ncustom time:%v\n", time.Now().Sub(start)) *booksCpy3[0].Author.Country = 1136 booksCpy3[0].Category[0] = "geometry" booksCpy3[0].Price["Africa"] = "$34" print("booksCpy3",booksCpy3) print("books",books) }
運(yùn)行輸出:
books[0]={Tutorial {David 38 0xc000016178} 2020 [math art] map[Europe:$56]} country=1156
gob time:454.117µs
booksCpy[0]={Tutorial {David 38 0xc0000165d8} 2020 [literature art] map[America:$250 Europe:$56]} country=1134
books[0]={Tutorial {David 38 0xc000016178} 2020 [math art] map[Europe:$56]} country=1156
json time:170.338µs
(*booksCpy2)[0]={Tutorial {David 38 0xc000016878} 2020 [science art] map[Canada:$150 Europe:$56]} country=1135
books[0]={Tutorial {David 38 0xc000016178} 2020 [math art] map[Europe:$56]} country=1156
custom time:2.165µs
booksCpy3[0]={Tutorial {David 38 0xc0000168c8} 2020 [geometry art] map[Africa:$34 Europe:$56]} country=1136
books[0]={Tutorial {David 38 0xc000016178} 2020 [math art] map[Europe:$56]} country=1156
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何使用騰訊云go sdk 查詢對(duì)象存儲(chǔ)中最新文件
這篇文章主要介紹了使用騰訊云go sdk 查詢對(duì)象存儲(chǔ)中最新文件,這包括如何創(chuàng)建COS客戶端,如何逐頁(yè)檢索對(duì)象列表,并如何對(duì)結(jié)果排序以找到最后更新的對(duì)象,我們還展示了如何優(yōu)化用戶體驗(yàn),通過(guò)實(shí)時(shí)進(jìn)度更新和檢索多個(gè)文件來(lái)改進(jìn)程序,需要的朋友可以參考下2024-03-03GO web 數(shù)據(jù)庫(kù)預(yù)處理的實(shí)現(xiàn)
本文主要介紹了GO web 數(shù)據(jù)庫(kù)預(yù)處理的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10Go Asynq異步任務(wù)處理的實(shí)現(xiàn)
Asynq是一個(gè)新興的異步任務(wù)處理解決方案,它提供了輕量級(jí)的、易于使用的API,本文主要介紹了Go Asynq異步任務(wù)處理的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-06-06Golang 使用http Client下載文件的實(shí)現(xiàn)方法
今天小編就為大家分享一篇Golang 使用http Client下載文件的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07在Linux系統(tǒng)中安裝Go語(yǔ)言的詳細(xì)教程
這篇文章主要介紹了在Linux系統(tǒng)中安裝Go語(yǔ)言的詳細(xì)教程,由于國(guó)內(nèi)很多人對(duì)谷歌的盲目追捧,導(dǎo)致Go語(yǔ)言在國(guó)內(nèi)的人氣遠(yuǎn)超國(guó)外...需要的朋友可以參考下2015-06-06