JavaScriptを有効にしてください

【Golang】structに別名をつけてメソッドを継承?する方法

 ·  ☕ 2 分で読めます
by Renée French

by Renée French

最近なんだか疲れてて、ブログもあまり書けてないけど、なんとかやめずに続けてきたい。。
ここのところはGoでWebアプリを作ろうとしてちょっとずつやってる。
Goは標準ライブラリが充実してるし、勉強のためにもできるだけフレームワーク無しで作ってみたいと思ってる。

今回はアプリ内部で使うapiを作ってるときに調べたことのメモ

なにがしたいか?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
type Something struct {
	HappenedAt   time.Time
	HappenedDate time.Time
}

func main() {
	js, _ := json.Marshal(something)
	fmt.Println(string(js))
}

# 実行結果
{"HappenedAt":"2020-02-07T00:25:09.209870352+09:00","HappenedDate":"2020-02-07T00:25:09.209870648+09:00"}

こんなふうにstructをjsonにする際に、デフォルトだと
HappenedAtもHappenedDateも完全な時間がでちゃいますね。

これをDateの方は、2020-02-07とだけしたい。

解決策

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type Date time.Time

func (date Date) MarshalJSON() ([]byte, error) {
	return []byte(`"` + time.Time(date).Format("2006-01-02") + `"`), nil
}

type Something struct {
	HappenedAt   time.Time
	HappenedDate Date
}

func main() {
	something := Something{
		HappenedAt:   time.Now(),
		HappenedDate: Date(time.Now()),
	}

	js, _ := json.Marshal(something)
	fmt.Println(string(js))
}

# 実行結果
{"HappenedAt":"2020-02-07T00:41:40.816646918+09:00","HappenedDate":"2020-02-07"}

type

type表現をつかうと、structや型などに別名をつけることができます。
別名をつけると元のstructとは別のものとして扱われ、メソッドを追加したりオーバーライドすることができます。

time.TimeにDateという別名をつけ、json.Marshal()するときに呼ばれるMarshalJSONというメソッドをオーバーライドすることで、好きなようにフォーマット等を書き換えることができます。

メソッドの継承・・・はできないので

ただ、注意としてtypeで別名をつけたstructは元のstructのメソッドを継承しません。
だから、MarshalJSONも正確にはオーバーライドではなく新しくメソッドを作っているイメージ。

メソッドを継承しないので、Date.Format("...")のようにしてtime.TImeのメソッドをそのまま使うことができない。
元structのメソッドを使いたいときには、一旦元structにキャストする。

1
time.Time(date).Format("2006-01-02")

おわり

golangには継承の概念がないからこのあたり独特ですね。

共有