Heim  >  Artikel  >  Backend-Entwicklung  >  So implementieren Sie Deep Copy in Golang

So implementieren Sie Deep Copy in Golang

PHPz
PHPzOriginal
2023-04-24 14:46:184136Durchsuche

In der Go-Sprache (Golang) müssen wir oft Strukturen oder Objekte kopieren. Direkte Zuweisungen oder flaches Kopieren können zu Fehlern führen, die schwer zu debuggen sind. Daher ist eine tiefe Kopie unbedingt erforderlich. In diesem Artikel wird vorgestellt, wie Golang Deep Copy implementiert.

Das Konzept des Deep Copy

Deep Copy besteht darin, eine neue Kopie aller internen Attribute eines Objekts zu erstellen. Selbst wenn ein bestimmtes Attribut im Originalobjekt und in der Kopie geändert wird, wirkt es sich auf diese Weise nicht gegenseitig aus. Flaches Kopieren kopiert nur Zeiger und mehrere Objekte zeigen auf dieselbe Adresse. Das Ändern der Eigenschaften eines Objekts wirkt sich auf andere Objekte aus.

Deep-Copy-Methode in Golang

Methode 1: Verwenden Sie json.Marshal() und json.Unmarshal()

Diese Methode ist relativ einfach, Sie können json.Marshal() und json.Unmarshal() in der Standardbibliothek verwenden Funktion.

Zum Beispiel:

type Person struct {
    Name string
    Age int
}

person1 := &Person{"Lucas", 18}
var person2 Person

temp, _ := json.Marshal(person1) //使用json.Marshal()将person1转换成json格式
json.Unmarshal(temp, &person2) //使用json.Unmarshal()将json格式转换成person2实例

Allerdings hat diese Methode einige Nachteile. Zunächst müssen Sie sicherstellen, dass das konvertierte JSON-Format nicht denselben JSON wie das Feld hat, da der JSON sonst nicht wieder in die Struktur konvertiert werden kann. Zweitens müssen sowohl json.Marshal() als auch json.Unmarshal() das gesamte Objekt durchlaufen, was zu einer langsameren Geschwindigkeit führt. Daher kann es nicht für komplexe Datenstrukturen und Anwendungen verwendet werden, die eine effiziente Leistung erfordern.

Methode 2: Verwenden Sie die rekursive Methode

Rekursives Deep Copy ist die am häufigsten verwendete Methode. Durchlaufen Sie jedes Element im Objekt oder Array, kopieren Sie es direkt, wenn es sich um einen Basistyp handelt, oder rufen Sie die Deep-Copy-Funktion rekursiv auf, wenn es sich um einen komplexen Typ handelt. Der Code lautet wie folgt:

func DeepCopy(input interface{}) interface{} {
    if input == nil {
        return nil
    }

    switch reflect.TypeOf(input).Kind() {

    case reflect.Bool, reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64:
        return input

    case reflect.Struct:
        in := reflect.ValueOf(input)
        out := reflect.New(in.Type()).Elem()

        for i := 0; i < in.NumField(); i++ {
            out.Field(i).Set(DeepCopy(in.Field(i).Interface()))
        }
        return out.Interface()

    case reflect.Array, reflect.Slice:
        in := reflect.ValueOf(input)
        out := reflect.MakeSlice(in.Type(), in.Len(), in.Cap())

        for i := 0; i < in.Len(); i++ {
            out.Index(i).Set(DeepCopy(in.Index(i).Interface()))
        }
        return out.Interface()

    case reflect.Map:
        in := reflect.ValueOf(input)
        out := reflect.MakeMapWithSize(in.Type(), in.Len())

        for _, key := range in.MapKeys() {
            out.SetMapIndex(DeepCopy(key.Interface()).(reflect.Value), DeepCopy(in.MapIndex(key).Interface()).(reflect.Value))
        }
        return out.Interface()

    default:
        panic(fmt.Sprintf("Unable to deepcopy object of type %v", reflect.TypeOf(input)))
    }
}

In diesem Code verwenden wir zunächst Reflect.TypeOf(), um den Objekttyp abzurufen, und rufen dann basierend auf der Typdefinition verschiedene Deep-Copy-Funktionen auf.

Wir können gängige Typen testen:

type Person struct {
    Name string
    Age int
}

type Object struct {
    Num int
    Str string
    Slice []int
    Map map[string]int
    Person Person
}

func main() {

    obj1 := &Object{1, "hello", []int{2, 3}, map[string]int{"age": 18}, Person{"Lucas", 20}}

    //深拷贝
    obj2 := DeepCopy(obj1)

    //修改obj1的Name字段
    obj1.Person.Name = "Nina"

    fmt.Println("obj1:", obj1)
    fmt.Println("obj2:", obj2)
}

Die Ausgabeergebnisse lauten wie folgt:

obj1: &{1 hello [2 3] map[age:18] {Nina 20}}
obj2: &{1 hello [2 3] map[age:18] {Lucas 20}}

Es ist ersichtlich, dass die Werte von obj1 und obj2 unterschiedlich sind und eine Änderung des Werts von obj1 keine Auswirkungen auf obj2 hat.

Zusammenfassung

In diesem Artikel werden zwei Methoden zum Deep Copying in Golang vorgestellt. Für einfache Strukturen können Sie json.Marshal() und json.Unmarshal() verwenden. Bei komplexen Datenstrukturen können rekursive Methoden zum Deep Copying eingesetzt werden. Bei der Durchführung einer Tiefenkopie müssen Sie auf die Beurteilung des Datentyps achten, um unnötige Fehler zu vermeiden.

Das obige ist der detaillierte Inhalt vonSo implementieren Sie Deep Copy in Golang. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn