ホームページ  >  記事  >  バックエンド開発  >  ## Go でポインター レシーバーを使用して型のインスタンスをコピーできないのはなぜですか?

## Go でポインター レシーバーを使用して型のインスタンスをコピーできないのはなぜですか?

Linda Hamilton
Linda Hamiltonオリジナル
2024-10-25 05:03:02171ブラウズ

## Why Can't I Just Copy Instances of Types With Pointer Receivers in Go?

ポインタ レシーバとインスタンスのコピーについて

Go では、値レシーバまたはポインタ レシーバのいずれかを使用してメソッドを定義できます。型 T のすべてのメソッドが T 自体のレシーバー型を持つ場合、そのメソッドのいずれかを呼び出すと必然的にコピーが作成されるため、その型のインスタンスを安全にコピーできます。

ただし、型が異なる場合は状況が変わります。ポインターレシーバーを備えたメソッドがあります。この場合、内部不変条件に違反する可能性があるため、その型のインスタンスのコピーは避けるべきです。

ポインターのコピーの問題

を説明する例を考えてみましょう。問題。値 v とポインター p の 2 つのフィールドを持つ Wrapper 型があるとします。 v と p の指定された値の両方に同じ数値を格納するつもりです。これを確実にするために、ポインター レシーバーを備えた Set メソッドを提供します。

<code class="go">type Wrapper struct {
    v int
    p *int
}

func (w *Wrapper) Set(v int) {
    w.v = v
    *w.p = v
}</code>

Wrapper のインスタンスがあり、Set メソッドを呼び出すと、p のポイントされた値が変更されます。ただし、インスタンスのコピーを作成すると、コピーは元のインスタンスと同じポインタ値 p を共有します。これは、いずれかのインスタンスで後続のメソッド呼び出しが両方のコピーに影響することを意味します。

例:

<code class="go">a := Wrapper{v: 0, p: new(int)}
b := a

fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)

a.Set(1)
fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)</code>

出力:

a.v=0, a.p=0;  b.v=0, b.p=0
a.v=1, a.p=1;  b.v=0, b.p=1

Inこの例では、b.v が *b.p と等しくないため、a.Set(1) が呼び出された後、b の値は無効になります。これは、a と b の両方のポインター p が同じ基になる値を指しているためです。

このような問題を回避するには、ポインター レシーバーを含むメソッドを使用するときにポインター値を操作することをお勧めします。あるいは、型が値レシーバーのみを持つことができる場合は、メソッド呼び出しに関係なく、その型のインスタンスを安全にコピーできます。

以上が## Go でポインター レシーバーを使用して型のインスタンスをコピーできないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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