日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

golang?對象深拷貝的常見方式及性能_Golang

作者:??whoops本尊???? ? 更新時間: 2022-08-11 編程語言

關于golang拷貝的概念

Go語言中所有賦值操作都是值傳遞,如果結構中不含指針,則直接賦值就是深度拷貝;如果結構中含有指針(包括自定義指針,以及切片,map等使用了指針的內置類型),則數(shù)據(jù)源和拷貝之間對應指針會共同指向同一塊內存,這時深度拷貝需要特別處理。目前,有三種方法,一是用gob序列化成字節(jié)序列再反序列化生成克隆對象;二是先轉換成json字節(jié)序列,再解析字節(jié)序列生成克隆對象;三是針對具體情況,定制化拷貝。前兩種方法雖然比較通用但是因為使用了reflex反射,性能比定制化拷貝要低出2個數(shù)量級,所以在性能要求較高的情況下應該盡量避免使用前兩者。

完整代碼

package json
import (
   "bytes"
   "encoding/gob"
   "encoding/json"
   "fmt"
   "testing"
)
/**
 * @Description: 請求信息
 */
type BidRequest struct {
   ID     string  `json:"id"`
   Imp    []*Imp  `json:"imp"`
   Device *Device `json:"device"`
}
/**
 * @Description: imp對象
 */
type Imp struct {
   ID          string  `json:"id"`
   Tagid       string  `json:"tagid"`
   Bidfloor    float64 `json:"bidfloor"`
}
/**
 * @Description: 設備信息
 */
type Device struct {
   Ua         string `json:"ua"`
   IP         string `json:"ip"`
   Geo        *Geo   `json:"geo"`
   Make       string `json:"make"`
   Model      string `json:"model"`
   Os         string `json:"os"`
   Osv        string `json:"osv"`
}
/**
 * @Description: 地理位置信息
 */
type Geo struct {
   Lat     int    `json:"lat"`
   Lon     int    `json:"lon"`
   Country string `json:"country"`
   Region  string `json:"region"`
   City    string `json:"city"`
}
/**
 * @Description: 利用gob進行深拷貝
 */
func DeepCopyByGob(src,dst interface{}) error {
   var buffer bytes.Buffer
   if err := gob.NewEncoder(&buffer).Encode(src); err != nil {
      return err
   }
   return gob.NewDecoder(&buffer).Decode(dst)
}
/**
 * @Description: 利用json進行深拷貝
 */
func DeepCopyByJson(src,dst *BidRequest) error{
   if tmp, err := json.Marshal(&src);err!=nil{
      return err
   }else {
      err = json.Unmarshal(tmp, dst)
      return err
   }
}

/**
 * @Description: 通過自定義進行copy
 */
func DeepCopyByCustom(src,dst *BidRequest){
   dst.ID=src.ID
   dst.Device=&Device{
      Ua: src.Device.Ua,
      IP: src.Device.IP,
      Geo: &Geo{
         Lat: src.Device.Geo.Lat,
         Lon: src.Device.Geo.Lon,
      },
      Make: src.Device.Make,
      Model: src.Device.Model,
      Os: src.Device.Os,
      Osv: src.Device.Osv,
   }
   dst.Imp=make([]*Imp,len(src.Imp))
   for index,imp:=range src.Imp{
      //注意此處因為imp對象里無指針對象,所以可以直接使用等于
      dst.Imp[index]=imp
   }
}

func initData()*BidRequest  {
   str:="{"id":"MM7dIXz4H05qtmViqnY5dW","imp":[{"id":"1","tagid":"3979722720","bidfloor":0.01}],"device":{"ua":"Mozilla/5.0 (Linux; Android 10; SM-G960N Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.115 Mobile Safari/537.36 (Mobile; afma-sdk-a-v212621039.212621039.0)","ip":"192.168.1.0","geo":{"lat":0,"lon":0,"country":"KOR","region":"KR-11","city":"Seoul"},"make":"samsung","model":"sm-g960n","os":"android","osv":"10"}}"
   ans:=new(BidRequest)
   json.Unmarshal([]byte(str),&ans)
   return ans
}

/**
 * @Description: 壓測深拷貝 -gob
 */
func BenchmarkDeepCopy_Gob(b *testing.B)  {
   src:=initData()
   b.ResetTimer()
   for i:=0;i<b.N;i++{
      DeepCopyByGob(src,new(BidRequest))
   }
}

/**
 * @Description: 壓測深拷貝 -json
 */
func BenchmarkDeepCopy_Json(b *testing.B)  {
   src:=initData()
   b.ResetTimer()
   for i:=0;i<b.N;i++{
      DeepCopyByJson(src,new(BidRequest))
   }
}
/**
 * @Description: 壓測深拷貝 -custom
 */
func BenchmarkDeepCopy_custom(b *testing.B)  {
   src:=initData()
   b.ResetTimer()
   for i:=0;i<b.N;i++{
      DeepCopyByCustom(src,new(BidRequest))
   }
}
/**
 * @Description: 測試拷貝是否ok
 */
func TestCpoyIsOk(t *testing.T)  {
   src:=initData()
   //1.gob
   dst01:=new(BidRequest)
   DeepCopyByGob(src,dst01)
   bs01, _ := json.Marshal(dst01)
   fmt.Printf("%v\n",string(bs01))
   //2.json
   dst02:=new(BidRequest)
   DeepCopyByJson(src,dst02)
   bs02, _ := json.Marshal(dst02)
   fmt.Printf("%v\n",string(bs02))
   //3.custom
   dst03:=new(BidRequest)
   DeepCopyByCustom(src,dst03)
   bs03, _ := json.Marshal(dst02)
   fmt.Printf("%v\n",string(bs03))
}

先執(zhí)行 TestCpoyIsOk,驗證三種方式的輸出是否ok,其驗證結果如下:

benmark三種copy方式:

執(zhí)行命令?go test -bench=. -benchmem?可以同時查看到每次操作的內存和耗時的情況

總結

可以看到 從性能上來講 custom>json>gob,從代碼數(shù)量上來講 gob>json>custom ,因此具體使用時應該充分考慮性能和代碼復雜度,若性能要求不是很高建議gob方法,其比較簡潔并且利于生成工具包,若要求性能則盡量使用custom,此處不偷懶可以提高性能哦。若是性能要求在中間,則可以使用json先序列化,再反序列化賦值。

原文鏈接:https://juejin.cn/post/7110861544698675208

欄目分類
最近更新