Go のポインター レシーバー メソッドを使用した単純な型の値の変更
Go では、基本型に基づいてカスタム型を作成し、その機能を拡張できますポインタ受信メソッドを介して。ただし、ポインター レシーバー メソッドを通じて単純型の値を変更しようとするときに生じる一般的な疑問があります。
次の例を考えてみましょう。
package main import ( "fmt" "strconv" ) type FooInt int func (fi *FooInt) FromString(i string) { num, _ := strconv.Atoi(i) tmp := FooInt(num) fi = &tmp // Attempt to modify the pointer } func main() { var fi *FooInt fi.FromString("5") fmt.Printf("%v\n", fi) // Prints <nil>, not the expected 5 }
なぜポインター fi は fi になるのですか? main() で宣言された値は tmp のアドレスに変更されませんか?
説明
Go で関数またはメソッドを呼び出すと、レシーバーを含むすべての引数が返されます。 、コピーとして渡されます。これは、関数/メソッド内から元のポインター値を変更できないことを意味します。
上記の例では、FromString メソッドの fi は、main() で宣言されたポインターのコピーです。 fi を tmp のアドレスに割り当てると、コピーの値が変更されるだけになります。元のポインタは変更されません。
解決策
この問題には 3 つの一般的な解決策があります。
1.ポインタを返す:
func (fi *FooInt) FromString(i string) *FooInt { num, _ := strconv.Atoi(i) tmp := FooInt(num) return &tmp } func main() { var fi *FooInt fi = fi.FromString("5") fmt.Printf("%v %v\n", fi, *fi) // Prints 0xc0000b4020 5 }
2.ポインタ引数を渡す:
func (fi *FooInt) FromString(i string, p **FooInt) { num, _ := strconv.Atoi(i) tmp := FooInt(num) *p = &tmp } func main() { var fi *FooInt fi = new(FooInt) // Ensure non-nil receiver fi.FromString("5", &fi) fmt.Printf("%v %v\n", fi, *fi) // Prints 0xc0000b4020 5 }
3.非 Nil 受信者の確認:
func (fi *FooInt) FromString(i string) { num, _ := strconv.Atoi(i) *fi = FooInt(num) } func main() { var fi *FooInt fi = new(FooInt) // Ensure non-nil receiver fi.FromString("5") fmt.Printf("%v %v\n", fi, *fi) // Prints 0xc0000b4020 5 }
以上がGo でポインター レシーバー メソッドを介して単純型の値を変更できないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。