###NoMethod
Go言語、例えばJSONで、特に構造体などの(Un)Marshalerインターフェースを実装するとき、
外部ライブラリのJSONパーサを利用したかったり、ちょっとした処理を追加したいだけで基本的な処理は標準ライブラリと同じ処理をしてほしいときがあります。
しかし単に呼び直すと再実装されたMarshalメソッドを呼び出すことになるのでループしてしまいます。
メソッドを持たない別の型を宣言しラップすることでこれを解決できます。
type Gopher struct{}
func (g *Gopher) MarshalJSON() ([]byte, error) {
type NoMethod Gopher
g.onJSONEncoding() //行いたい処理
raw := NoMethod(*g)
return json.Marshal(raw)
}
###応用
もう一つ、例えばTime型などjsonでサポートされていない型に対応させたいとき、Unmarshalメソッドを実装するために別の型を宣言しますがその型をそのままメンバにするとtime.Time型を直接使うのと比べていろいろと扱いづらいと思います。
これは元の型を埋め込んでいる冗長なメンバを持った一時的な構造体を定義することで解決できます。
type Time time.Time
func (t *Time) UnmarshalJSON(b []byte) error {
var tt time.Time
tt, err := time.Parse(`"2006-01-02"`, string(b))
*t = Time(tt)
return err
}
type Gopher struct {
Birthday time.Time
}
func (g *Gopher) UnmarshalJSON(data []byte) error {
type NoMethod Gopher
var gg struct {
Birthday Time
*NoMethod
}
gg.NoMethod = (*NoMethod)(g)
if err := json.Unmarshal(data, &gg); err != nil {
return err
}
g.Birthday = time.Time(gg.Birthday)
return nil
}
GoPlayground
https://play.golang.org/p/lVSwnkJFDLv