Go でのマップ インデックスの逆参照
マップ内の値を操作するときは、マップのポインター レシーバーの動作を認識することが重要ですエントリ。以下のコードに例示されているように、マップ インデックスでポインター レシーバー メソッドを呼び出そうとするときによくある落とし穴が発生します。
package main import "fmt" type item struct { itemName string amount int } type Cashier struct { items map[int]item cash int } func (i *item) GetAmount() int { return i.amount } func main() { x := Cashier{} x.AddItem("item1", 13) f := x.GetItems() fmt.Println(f[0].GetAmount()) // Error: cannot call pointer method on f[0] }
このコードでは、GetAmount メソッドは項目を直接操作するポインター レシーバーとして定義されています。構造体。ただし、 f[0].GetAmount() を呼び出すと、「f[0] でポインター メソッドを呼び出すことができません」というエラーが表示されます。これは、マップが拡大または縮小するとアドレスが変更される可能性があるため、マップ エントリを直接アドレス指定できないためです。
この動作の理由は、Go がマップを実装する方法にあります。マップは内部的にハッシュ テーブルとして表され、パフォーマンスを最適化するために実行時にサイズを変更できます。その結果、マップ エントリのアドレスが時間の経過とともに変化する可能性があり、ポインタ レシーバ メソッドに引数として渡すことが無効になります。
この問題を解決するには、マップのコピーを作成することが 1 つの方法です。ポインタ レシーバを使用する代わりにエントリを追加します。これは、まずインデックスを使用してマップから値を取得し、次にその値のコピーを作成することで実現できます。
func main() { x := Cashier{} x.AddItem("item1", 13) f := x.GetItems() itemCopy := f[0] fmt.Println(itemCopy.GetAmount()) // No error }
この場合、itemCopy は f[0] に格納されている値のコピーです。これを使用すると、エラーが発生することなくポインタ レシーバ メソッドを呼び出すことができます。
マップ エントリを使用してポインタ レシーバの動作を理解することで、開発者はこの落とし穴を回避してコードを作成できます。マップ値に対して正しく動作します。
以上がGo マップ インデックスでポインター レシーバー メソッドを呼び出せないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。