Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk melaksanakan salinan dalam dalam golang

Bagaimana untuk melaksanakan salinan dalam dalam golang

PHPz
PHPzasal
2023-04-24 14:46:184045semak imbas

Dalam bahasa Go (golang), kita selalunya perlu menyalin struktur atau objek. Tugasan langsung atau penyalinan cetek boleh menyebabkan ralat yang sukar untuk dinyahpepijat. Oleh itu, salinan yang mendalam sangat diperlukan. Artikel ini akan memperkenalkan cara golang melaksanakan salinan dalam.

Konsep salinan dalam

Salinan dalam adalah untuk mencipta salinan baharu semua sifat dalaman sesuatu objek. Dengan cara ini, walaupun atribut tertentu diubah suai dalam objek asal dan salinan, ia tidak akan menjejaskan satu sama lain. Salinan cetek hanya menyalin penunjuk, dan berbilang objek menghala ke alamat yang sama. Mengubah suai sifat satu objek akan mempengaruhi objek lain.

Kaedah salinan dalam dalam golang

Kaedah 1: Gunakan json.Marshal() dan json.Unmarshal()

Kaedah ini agak mudah dan boleh digunakan dalam standard perpustakaan Fungsi json.Marshal() dan json.Unmarshal().

Contohnya:

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实例

Walau bagaimanapun, kaedah ini mempunyai beberapa kelemahan. Pertama sekali, anda perlu memastikan bahawa format json yang ditukar tidak mempunyai json yang sama dengan medan, jika tidak, json tidak boleh ditukar kembali kepada struktur. Kedua, kedua-dua json.Marshal() dan json.Unmarshal() perlu melintasi keseluruhan objek, menghasilkan kelajuan yang lebih perlahan. Oleh itu, ia tidak boleh digunakan untuk struktur data kompleks dan aplikasi yang memerlukan prestasi cekap.

Kaedah 2: Gunakan kaedah rekursif

Salinan dalam rekursif ialah kaedah yang paling biasa digunakan. Lintas setiap elemen dalam objek atau tatasusunan, salin terus jika ia adalah jenis asas, atau panggil fungsi salinan dalam secara rekursif jika ia adalah jenis yang kompleks. Kodnya adalah seperti berikut:

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)))
    }
}

Dalam kod ini, kami mula-mula menggunakan reflect.TypeOf() untuk mendapatkan jenis objek, dan kemudian memanggil fungsi salinan dalam yang berbeza berdasarkan definisi jenis.

Kita boleh menguji jenis biasa:

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)
}

Keputusan output adalah seperti berikut:

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

Dapat dilihat bahawa nilai obj1 dan obj2 adalah berbeza. Ubah suai nilai obj1 dan Tidak akan menjejaskan obj2.

Ringkasan

Artikel ini memperkenalkan dua kaedah penyalinan dalam dalam golang. Untuk struktur mudah, anda boleh menggunakan json.Marshal() dan json.Unmarshal(). Untuk struktur data yang kompleks, kaedah rekursif boleh digunakan untuk penyalinan dalam. Apabila melakukan salinan dalam, anda perlu memberi perhatian kepada pertimbangan jenis data untuk mengelakkan ralat yang tidak perlu.

Atas ialah kandungan terperinci Bagaimana untuk melaksanakan salinan dalam dalam golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn