package main import "fmt" type Aer interface{ Name()string PrintName() } type A struct { } func (a *A) Name() string { return "a" } func (a *A) PrintName() { fmt.Println(a.Name()) } type B struct { A } func (b *B) Name() string { return "b" } func getAer() Aer { return &B{} } func main() { a := getAer() a.printName() }
この実装では、golang は a を出力します。この実装は、C、Java、Python の通常の b の実装に違反します。上記の言語の考え方により、一度習慣化されます。が形成されているため、この実装は多くの予期せぬ事態を引き起こすでしょう。
昨日、golang 実践グループ
で賞賛されている兄弟 (この兄弟は、私が尋ねた上記の質問を知っていて、これが golang の実装方法であると言っています) が、UnmarshalJSON のとき、なぜ、テスト フィールドに値が割り当てられておらず、golang で問題が発生しました。コードは次のとおりです:
package main import ( "encoding/json" "fmt" ) type request struct { Operations map[string]op `json:"operations"` } type op struct { operation Test string `json:"test"` } type operation struct { Width int `json:"width"` Height int `json:"height"` } func (o *operation) UnmarshalJSON(b []byte) error { type xoperation operation xo := &xoperation{Width: 500, Height: 500} if err := json.Unmarshal(b, xo); err != nil { return err } *o = operation(*xo) return nil } func main() { jsonStr := `{ "operations": { "001": { "test":"test", "width": 100 } } }` req := request{} json.Unmarshal([]byte(jsonStr), &req) fmt.Println(req) }
この問題の本質は、私が提起した問題と同じです。がopに埋め込まれているので、jsonパッケージにはUnmarshalerインターフェースに準拠したUnmarshalJSONが存在するため、内部でインターフェースを使って処理する場合はopは満たされますが、実際に処理されるのはオペレーション、つまりこの操作は UnmarshalJSON を実行するエンティティとして使用され、奇妙なエラー メッセージが表示されます。
これは、golang の実装において非常に見苦しい場所だと思います。
Brother Mouse の発言によると、言語の実装ルールはわかっていても間違いが起こりやすい場合、それは落とし穴です。
この Golang の落とし穴は、おそらく将来的には埋められなければならないでしょう。