Go でのインターフェイス値のコピー
Go のインターフェイス値は、動的型と基礎となる具体的な値をカプセル化します。あるインターフェイス値を別のインターフェイス値に割り当てると、元の具体的な値自体ではなく、基になる値がコピーされます。これにより、インターフェイスや構造体へのポインターを操作するときに予期しない動作が発生する可能性があります。
次の例を考えてみましょう:
type User interface { Name() string SetName(name string) } type Admin struct { name string } func (a *Admin) Name() string { return a.name } func (a *Admin) SetName(name string) { a.name = name }
この例では、管理者はユーザー インターフェイスを実装します。 User 型の user1 変数を作成し、Admin 構造体へのポインターを使用して初期化します。
var user1 User user1 = &Admin{name: "user1"}
次に、新しい user2 変数を作成し、それに user1 の値を割り当てます。
var user2 User user2 = user1
ここでの問題は、user1 と user2 の両方が同じ Admin インスタンスを参照していることです。 user2 の名前を変更すると、user1 の名前も変更されます。これは、インターフェイス値には基礎となる Admin 構造体へのポインターのみが含まれるためです。
これを防ぐには、user2 用に新しい Admin 構造体を作成する必要があります。リフレクションを使用してこれを実現できます。
var user2 User padmin := user1.(*Admin) // Obtain *Admin pointer admin2 := *padmin // Make a copy of the Admin struct user2 = &admin2 // Wrap its address in another User
これで、user2 の名前を変更しても user1 には影響しなくなりました。
ただし、この解決策では、インターフェイス値の具体的な型を知る必要があります。あらかじめ。より一般的な解決策は、リフレクションを使用して、インターフェイス値の動的型の新しいインスタンスを作成することです。
var user2 User if reflect.TypeOf(user1).Kind() == reflect.Ptr { // Pointer: user2 = reflect.New(reflect.ValueOf(user1).Elem().Type()).Interface().(User) } else { // Not pointer: user2 = reflect.New(reflect.TypeOf(user1)).Elem().Interface().(User) }
この解決策は、ポインタ インターフェイス値と非ポインタ インターフェイス値の両方で機能します。
以上が基礎となるデータの共有を避けるために、Go でインターフェイス値を適切にコピーするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。