よく見かける構造体の使い方のざっくりメモ。
名前はまったく思いつかなかったので、ケース別に。
Goroutineを使わないもの縛り。
コンストラクタの設定をする
type Foo struct {
Param Param
}
type Param struct {
Name string
}
// コンストラクタ
func NewFoo(name string) *Foo {
p := Param{name}
return &Foo{p}
}
func main() {
f := NewFoo("Hello")
fmt.Println(f.Param.Name) // "Hello"
}
Goにはコンストラクタがないので、New
を接頭語にした関数を用意して
そこに初期値を設定出来るようにする。
エラー出力を整形する
type Foo struct {
Name string
}
func (f Foo) Error() string {
return fmt.Sprintf("Error: Foo's %s error message.", f.Name)
}
func main() {
f := Foo{"Special"}
panic(f) // panic: Error: Foo's Special error message.
}
errorにはinterfaceが定義されている。
type error interface {
Error() string
}
func Error() string
を実装すれば、どの構造体をpanic
などで表示されるフォーマットを定義することが出来る。
基本型にメソッドを追加する
type num int
func (n *num) IsEven() bool {
return (*n % 2) == 0
}
func main() {
var n num
for n = 1; n < 10; n++ {
fmt.Println(n, ":", n.IsEven())
}
}
基本型にメソッドを追加して、普段は通常の型と同じ使い方をしながら
一部の処理でメソッドを呼び出すようにする。
テンプレートからファイルを作成して実行する
(ここの主旨とズレるけれど)
http://play.golang.org/p/paI3ZPzRel
(Playgroundでは動かない)
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"text/template"
)
type Params struct {
Message string
}
func main() {
dir, _ := ioutil.TempDir("", "foo")
defer os.RemoveAll(dir)
m := Params{"Hello World"}
path := filepath.Join(dir, "main.go")
f, ) := os.Create(path)
if err != nil {
panic(err)
}
defer f.Close()
err = tpl.Execute(f, m)
if err != nil {
panic(err)
}
cmd := exec.Command("go", "run", path)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err = cmd.Run(); err != nil { // "Hello World"
fmt.Errorf("`go run` failed: ", err)
}
}
var tpl = template.Must(template.New("foo.tmpl").Parse(`
package main
import "fmt"
func main() {
fmt.Println("{{ .Message }}")
}
`))
revelやgooseなどで使われている。
一旦Configの値をソースコードとしてファイルに書き出してからそれを実行。
これがベストプラクティスなのかはよくわかりません。