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