go切片的深拷贝

文章发布于 2023-08-28

在 Go 中,对切片进行深拷贝,需要创建一个新的切片并且其中的元素是原始切片中元素的副本,然后逐个复制原始切片中的元素。这对于切片中的非基本数据类型(如切片、映射、结构体等)是特别重要,因为切片只存储引用。

以下是一个示例,展示了如何对非基本数据类型的切片进行深拷贝:

package main

import (
    "fmt"
    "reflect"
)

func deepCopy(slice interface{}) interface{} {
    sliceValue := reflect.ValueOf(slice)
    if sliceValue.Kind() != reflect.Slice {
        panic("Input is not a slice")
    }

    // 创建新的切片
    newSlice := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len(), sliceValue.Len())

    for i := 0; i < sliceValue.Len(); i++ {
        // 复制切片中的元素
        element := reflect.New(sliceValue.Index(i).Type()).Elem()
        element.Set(sliceValue.Index(i))
        newSlice.Index(i).Set(element)
    }

    return newSlice.Interface()
}

func main() {
    originalSlice := []interface{}{1, "two", []int{3, 4, 5}}

    // 对切片进行深拷贝
    copiedSlice := deepCopy(originalSlice)

    // 修改原始切片的内容
    originalSlice[0] = 100
    originalSlice[2].([]int)[0] = 300

    // 打印两个切片的内容
    fmt.Println(originalSlice)    // [100 two [300 4 5]]
    fmt.Println(copiedSlice)     // [1 two [3 4 5]]
}

这个示例中,deepCopy 函数通过使用反射逐个复制切片中的元素来实现深拷贝。请注意,这只是一个基本的示例,对于复杂的数据类型和嵌套的结构可能需要更多的处理。

但请注意,使用反射会导致性能下降,因此只在必要的情况下才使用。对于大部分情况,最好的做法是明确地编写复制逻辑以及创建新的数据结构来实现深拷贝。