ホームページ >バックエンド開発 >Golang >Go でインターフェイス値のディープ コピーを作成するにはどうすればよいですか?

Go でインターフェイス値のディープ コピーを作成するにはどうすればよいですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-07 20:57:12740ブラウズ

How to Achieve a Deep Copy of Interface Values in Go?

Go でのインターフェイス値の深いコピー

Go でインターフェイス値を直接コピーすると、浅いコピーが作成され、コピーされたものに変更が加えられます。値はオリジナルにも影響します。これは、インターフェイスが基礎となる具象型への参照を保持しているためです。

名前変更の原因

提供されたコードの問題を理解するために、インターフェイス値がどのように機能するかを分析してみましょう。 。ユーザー インターフェイスはコントラクトを表し、管理者とユーザーの両方がこのコントラクトを実装します。 user1 を user2 に割り当てるときは、基本的に同じ管理インスタンスへの参照を作成することになります。 user2 の Name() メソッドを変更すると、共有 Admin インスタンスが直接変更され、その結果、user1 の名前も変更されます。

リフレクションによるソリューション

ディープ コピーを実現するには、以下が必要です。基礎となる具象型の新しいインスタンスを作成し、それを新しいユーザー インターフェイス値でラップします。これを行う 1 つの方法は、リフレクションを使用することです。関数reflect.ValueOf()とreflect.Elem()を使用して、user1に格納されている基になる値を取得できます。次に、reflect.New() を使用して同じタイプの新しいインスタンスを作成し、reflect.MethodByName() を使用して Name() メソッドを取得します。最後に、新しいインスタンスで SetName() メソッドを呼び出し、それを新しいユーザー インターフェイス値でラップできます。

func CloneUser(user User) User {
    val := reflect.ValueOf(user)
    if val.Kind() != reflect.Ptr {
        panic("expected pointer")
    }
    elem := val.Elem()
    t := elem.Type()
    newElem := reflect.New(t).Elem()
    newElem.MethodByName("SetName").Call([]reflect.Value{reflect.ValueOf(newElem.String())})
    return newElem.Interface().(User)
}

この関数を使用すると、元のインスタンスに影響を与えないコピーを作成できます。

var user2 User = CloneUser(user1)
user2.SetName("user2")
fmt.Println(user1.Name(), user2.Name()) // Outputs: user1 user2

以上がGo でインターフェイス値のディープ コピーを作成するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。