欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語言深度拷貝工具deepcopy的使用教程

 更新時間:2022年09月15日 11:25:43   作者:Go學(xué)堂  
今天給大家推薦的工具是deepcopy,一個可以對指針、接口、切片、結(jié)構(gòu)體、Map都能進行深拷貝的工具,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)學(xué)習(xí)

今天給大家推薦的工具是deepcopy,一個可以對指針、接口、切片、結(jié)構(gòu)體、Map都能進行深拷貝的工具。在Go中需要對一個變量進行拷貝時分淺拷貝和深拷貝。淺拷貝就是拷貝后就是無論改變新值還是原值都對對另一個產(chǎn)生影響,比如切片。而深拷貝則是將目標值完全拷貝一份,消除這種影響。

實現(xiàn)原理分析

深拷貝的實現(xiàn)原理本質(zhì)上是通過反射實現(xiàn)。通過將源對象轉(zhuǎn)換成接口,再對接口通過反射判斷其類型,進而進行深度拷貝。如下就是該包的完全實現(xiàn):

package deepcopy

import (
	"reflect"
	"time"
)

// Interface for delegating copy process to type
type Interface interface {
	DeepCopy() interface{}
}

// Iface is an alias to Copy; this exists for backwards compatibility reasons.
func Iface(iface interface{}) interface{} {
	return Copy(iface)
}

// Copy creates a deep copy of whatever is passed to it and returns the copy
// in an interface{}.  The returned value will need to be asserted to the
// correct type.
func Copy(src interface{}) interface{} {
	if src == nil {
		return nil
	}

	// Make the interface a reflect.Value
	original := reflect.ValueOf(src)

	// Make a copy of the same type as the original.
	cpy := reflect.New(original.Type()).Elem()

	// Recursively copy the original.
	copyRecursive(original, cpy)

	// Return the copy as an interface.
	return cpy.Interface()
}

// copyRecursive does the actual copying of the interface. It currently has
// limited support for what it can handle. Add as needed.
func copyRecursive(original, cpy reflect.Value) {
	// check for implement deepcopy.Interface
	if original.CanInterface() {
		if copier, ok := original.Interface().(Interface); ok {
			cpy.Set(reflect.ValueOf(copier.DeepCopy()))
			return
		}
	}

	// handle according to original's Kind
	switch original.Kind() {
	case reflect.Ptr:
		// Get the actual value being pointed to.
		originalValue := original.Elem()

		// if  it isn't valid, return.
		if !originalValue.IsValid() {
			return
		}
		cpy.Set(reflect.New(originalValue.Type()))
		copyRecursive(originalValue, cpy.Elem())

	case reflect.Interface:
		// If this is a nil, don't do anything
		if original.IsNil() {
			return
		}
		// Get the value for the interface, not the pointer.
		originalValue := original.Elem()

		// Get the value by calling Elem().
		copyValue := reflect.New(originalValue.Type()).Elem()
		copyRecursive(originalValue, copyValue)
		cpy.Set(copyValue)

	case reflect.Struct:
		t, ok := original.Interface().(time.Time)
		if ok {
			cpy.Set(reflect.ValueOf(t))
			return
		}
		// Go through each field of the struct and copy it.
		for i := 0; i < original.NumField(); i++ {
			// The Type's StructField for a given field is checked to see if StructField.PkgPath
			// is set to determine if the field is exported or not because CanSet() returns false
			// for settable fields.  I'm not sure why.  -mohae
			if original.Type().Field(i).PkgPath != "" {
				continue
			}
			copyRecursive(original.Field(i), cpy.Field(i))
		}

	case reflect.Slice:
		if original.IsNil() {
			return
		}
		// Make a new slice and copy each element.
		cpy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap()))
		for i := 0; i < original.Len(); i++ {
			copyRecursive(original.Index(i), cpy.Index(i))
		}

	case reflect.Map:
		if original.IsNil() {
			return
		}
		cpy.Set(reflect.MakeMap(original.Type()))
		for _, key := range original.MapKeys() {
			originalValue := original.MapIndex(key)
			copyValue := reflect.New(originalValue.Type()).Elem()
			copyRecursive(originalValue, copyValue)
			copyKey := Copy(key.Interface())
			cpy.SetMapIndex(reflect.ValueOf(copyKey), copyValue)
		}

	default:
		cpy.Set(original)
	}
}

基本使用

拷貝切片

	a := []int{1,2,3}
	dst := deepcopy.Copy(a)
	a1 := dst.([]int)
	a1[0] = 2
	fmt.Println(a, a1) //a:[1 2 3] a1:[2 2 3]

拷貝map

	a := make(map[string]int)
	a["k1"] = 1
	a["k2"] = 2
	a["k3"] = 3
	dst := deepcopy.Copy(a)
	a1 := dst.(map[string]int)
	a1["k1"] = 10
	fmt.Println(a, a1) //a:map[k1:1 k2:2 k3:3] a1:map[k1:10 k2:2 k3:3]

更多項目詳情請查看如下鏈接。

開源項目地址:https://github.com/mohae/deepcopy

到此這篇關(guān)于Go語言深度拷貝工具deepcopy的使用教程的文章就介紹到這了,更多相關(guān)Go深度拷貝deepcopy內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言并發(fā)編程基礎(chǔ)上下文概念詳解

    Go語言并發(fā)編程基礎(chǔ)上下文概念詳解

    這篇文章主要為大家介紹了Go語言并發(fā)編程基礎(chǔ)上下文示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • 淺析Golang中make和new的用法區(qū)別

    淺析Golang中make和new的用法區(qū)別

    在Go語言中,有兩個比較雷同的內(nèi)置函數(shù),分別是new和make方法,二者都可以用來分配內(nèi)存,那他們有什么區(qū)別呢?下面就跟隨小編一起來學(xué)習(xí)一下吧
    2024-02-02
  • golang進程內(nèi)存控制避免docker內(nèi)oom

    golang進程內(nèi)存控制避免docker內(nèi)oom

    這篇文章主要為大家介紹了golang進程內(nèi)存控制避免docker內(nèi)oom示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • Golang中空的切片轉(zhuǎn)化成 JSON 后變?yōu)?nbsp;null 問題的解決方案

    Golang中空的切片轉(zhuǎn)化成 JSON 后變?yōu)?nbsp;null 問題的解決方案

    在 Golang 中,經(jīng)常需要將其他類型(例如 slice、map、struct 等類型)的數(shù)據(jù)轉(zhuǎn)化為 JSON 格式,有時候轉(zhuǎn)化的結(jié)果并不是預(yù)期中的,例如將一個空的切片轉(zhuǎn)化為 JSON 時,會變成"null",所以本文將給大家介紹一下解決方法,需要的朋友可以參考下
    2023-09-09
  • golang?sync.Cond同步機制運用及實現(xiàn)

    golang?sync.Cond同步機制運用及實現(xiàn)

    在?Go?里有專門為同步通信而生的?channel,所以較少看到?sync.Cond?的使用,不過它也是并發(fā)控制手段里的一種,今天我們就來認識下它的相關(guān)實現(xiàn),加深對同步機制的運用
    2023-09-09
  • Golang對MongoDB數(shù)據(jù)庫的操作簡單封裝教程

    Golang對MongoDB數(shù)據(jù)庫的操作簡單封裝教程

    mongodb官方?jīng)]有關(guān)于go的mongodb的驅(qū)動,因此只能使用第三方驅(qū)動,mgo就是使用最多的一種。下面這篇文章主要給大家介紹了關(guān)于利用Golang對MongoDB數(shù)據(jù)庫的操作簡單封裝的相關(guān)資料,需要的朋友可以參考下
    2018-07-07
  • 一文帶你輕松理解Go中的內(nèi)存逃逸問題

    一文帶你輕松理解Go中的內(nèi)存逃逸問題

    這篇文章主要給大家介紹Go中的內(nèi)存逃逸問題,文中通過代碼示例講解的非常詳細,對我們的學(xué)習(xí)或工作有一定的參考價值,感興趣的同學(xué)可以跟著小編一起來學(xué)習(xí)
    2023-06-06
  • Golang語言如何避免空指針引發(fā)的panic詳解

    Golang語言如何避免空指針引發(fā)的panic詳解

    簡單地說go語言的指針類型和C/C++的指針類型用法是一樣的,除了出去安全性的考慮,go語言增加了一些限制,這篇文章主要給大家介紹了關(guān)于Golang語言如何避免空指針引發(fā)panic的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • 詳解Go module的介紹及使用

    詳解Go module的介紹及使用

    module是一個相關(guān)Go包的集合,它是源代碼更替和版本控制的單元。這篇文章主要介紹了Go module的介紹及使用,需要的朋友可以參考下
    2020-10-10
  • 關(guān)于golang類型推斷和變量重聲明詳解

    關(guān)于golang類型推斷和變量重聲明詳解

    在Go語言中,類型推斷可以根據(jù)變量的初始化值自動推斷出變量的類型,而不需要顯式地聲明變量類型,變量重聲明可以在同一作用域內(nèi)重復(fù)聲明一個變量,只要其中至少一個是新的變量,本就簡單的給大家介紹一下golang類型推斷和變量重聲明,需要的朋友可以參考下
    2023-08-08

最新評論