1. ホーム
  2. go

[解決済み] 構造体の値をマップの値として設定すると、"cannot assign" エラーが発生するのはなぜですか?重複

2022-11-01 01:40:32

質問

Go の新機能。このエラーに遭遇し、その原因や根拠を見つけることができませんでした。

構造体を作成した場合、明らかに値の割り当てと再割り当てが問題なくできます。

type Person struct {
 name string
 age int
}

func main() {
  x := Person{"Andy Capp", 98}
  x.age = 99
  fmt.Printf("age: %d\n", x.age)
}

が、構造体がマップの中の1つの値である場合。

type Person struct {
     name string
     age int
 }

type People map[string]Person

func main() {
  p := make(People)
  p["HM"] = Person{"Hank McNamara", 39}
  p["HM"].age = p["HM"].age + 1
  fmt.Printf("age: %d\n", p["HM"].age)
}

私は cannot assign to p["HM"].age . これだけで、他の情報はありません。 http://play.golang.org/p/VRlSItd4eP

私はこれを回避する方法を見つけました。 incrementAge を作成し、それを呼び出してその結果をマップのキーに代入することです。 p["HM"] = p["HM"].incrementAge() .

しかし、私の質問は、この "cannot assign" エラーの理由は何ですか、そしてなぜ構造体の値を直接代入してはいけないのですか。

どのように解決するのですか。

p["HM"] は、通常の アドレス指定可能 の値です。 ハッシュマップは実行時に拡大することができます で、その値がメモリ内で移動してしまい、古い位置が古くなってしまうのです。もしマップ内の値が通常のアドレス可能な値として扱われた場合、それらの内部で map 実装の内部が公開されることになります。

そこで、代わりに p["HM"] は、"マップと呼ばれる少し変わったものです。 インデックス式 というフレーズを仕様で検索すると、読み込み、割り当て、インクリメント/デクリメント式(数値型用)での使用など、特定のことができることがわかります。しかし、すべてを行うことはできません。彼らは より を実装することもできましたが、物事をシンプルに保つためにそうしなかったのでしょう。

特に許可された操作の 1 つである通常の代入に変更します。別のアプローチ (コピーしまくるのを避けたいより大きな構造体に適しているかも?) は、次のとおりです。 マップの値を通常の古いポインターにする を作成し、それを介して基礎となるオブジェクトを変更することができます。

package main

import "fmt"

type Person struct {
    name string
    age  int
}

type People map[string]*Person

func main() {
    p := make(People)
    p["HM"] = &Person{"Hank McNamara", 39}
    p["HM"].age += 1
    fmt.Printf("age: %d\n", p["HM"].age)
}