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 サイトの他の関連記事を参照してください。