golang, yaml
Go で struct は embed (埋め込み) できる
1
2
3
4
| type ReadWriter struct {
reader *Reader
writer *Writer
}
|
go では継承がないため、embed という形で field を引き継がせることができる。
interface の場合は interface のみを embed でき、struct の場合は interface, struct を embed できる。
参考:
さて、go で yaml を扱う際によく利用される gopkg.in の yaml.v2 には struct field tag にて flag を与えることができる。
yaml - GoDoc
この中で inline という flag があり、これを embed した struct と組み合わせると下記のように yaml 出力時に階層を1つ下げて export, import ができる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
type A struct {
Foo string `yaml:"foo"`
Bar int `yaml:"bar"`
}
type B struct {
EmA A
}
type C struct {
EmA A `yaml:"a,inline"`
}
func main(){
a := A{
Foo: "foo",
Bar: 1,
}
b := B{
EmA: a,
}
c := C{
EmA: a,
}
aBytes, _ := yaml.Marshal(a)
fmt.Printf("%s\n", aBytes)
bBytes, _ := yaml.Marshal(b)
fmt.Printf("%s\n", bBytes)
cBytes, _ := yaml.Marshal(c)
fmt.Printf("%s\n", cBytes)
}
|
この実行結果は下記のようになる。
1
2
3
4
5
6
7
8
9
| foo: foo
bar: 1
ema:
foo: foo
bar: 1
foo: foo
bar: 1
|
この embed して yaml では inline 化するメリットは、例えば Config 構造体のように、いくつかの config を束ねてファイルへ marshal したいケースで、不要な階層を1つ削れる点にある。
1
2
3
4
5
6
7
8
9
10
| configA:
foo: foo
bar: 1
configB:
baz: baz
// これを下記のように marshal できる
foo: foo
bar: 1
baz: baz
|
もちろん、これだと例えば baz field がどの config 構造体に紐づくか分かりづらいという観点もある。
そんなときは、struct field tag に、yaml:"git_api_url" というようなユニーク性を持つ名前を与えることで混乱は避けられる。