goのstructとinterface辺りのメモ

・ポインタはよしなにdereferenceしてくれる
http://golang.org/ref/spec#Selectors
http://play.golang.org/p/WtCuLsr824

package main

type T0 struct {
	x int
}

func (recv *T0) M0(){
	println("*T0:",recv.x)
}

type T1 struct {
	y int
}

func (recv T1) M1(){
	println("M1:",recv.y)
}

type T2 struct {
	z int
	T1
	*T0
}

func (recv *T2) M2(){
	println("*T2:",recv.z)
}

func main(){

	var p *T2 = &T2{3,T1{2},&T0{1}}

	println(p.z)
	println((*p).z)
	(*p).M2()
	p.M2()
	(*p).T1.M1()
	p.M1()
	(*(*p).T0).M0()
	p.M0()
	(*p).M0()
	
	(*T2).M2(p)
	(T1).M1(p.T1)
	(*T0).M0(p.T0)
}
3
3
*T2: 3
*T2: 3
M1: 2
M1: 2
*T0: 1
*T0: 1
*T0: 1
*T2: 3
M1: 2
*T0: 1


ポインタをよしなに扱ってくれるので以下のように呼び出せる (ただし当然M0()内でのrecvの変更は呼び出し元に影響しない)
http://play.golang.org/p/DE_2nzUOsq

package main

type T0 struct {
	x int
}

func (recv T0) M0(){
	recv.x = 4;
	println("*T0:",recv.x)
}

func main(){
	var t *T0 = &T0{2}
	t.M0()
	println(t.x)
}
*T0: 4
2


・interface type にはinterfaceを実装するものが入れられる.interace type から呼び出せるのはinterfaceで宣言されたメソッドのみ.interface type から特定のtypeに変換したい場合はtype assertionを使う
・以下の例では &Bar{}をtype Fooの変数に代入しているが, *Bar をレシーバとしてFoo()が定義されており interface Fooを満足しているでok.このとき別に type Foo のポインタを使うわけではない.
http://golang.org/ref/spec#Type_assertions
http://play.golang.org/p/aItoeCpxqx

package main

import "fmt"

type Foo interface {
	Foo() string
}

type Bar struct{}

type Boo struct{}

func (b *Bar) Foo() string {
	return "Bar: Foo()"
}

func (b *Bar) Bar() string {
	return "Bar: Bar()"
}

func (b *Boo) Foo() string {
	return "Boo: Foo()"
}

func (b *Boo) Boo() string {
	return "Boo: Boo()"
}

func main() {
	var f Foo = &Bar{}
	fmt.Println(f.Foo())
	if b, ok := f.(*Bar); ok {
		fmt.Println(b.Bar())
	}
	if b, ok := f.(*Boo); ok {
		fmt.Println(b.Boo())
	}
	
}
Bar: Foo()
Bar: Bar()


interface typeのポインタを使う例 (使い道ある?)
http://play.golang.org/p/-WK_XHE3lX

package main

import "fmt"

type Foo interface {
	Foo() string
}

type Bar struct{}

type Boo struct{}

func (b *Bar) Foo() string {
	return "Bar: Foo()"
}

func (b *Bar) Bar() string {
	return "Bar: Bar()"
}

func main() {
	var b *Bar = &Bar{}
	var pf *Foo = new(Foo)
	*pf = b
	fmt.Println((*pf).Foo())
}


・あるtypeの変数が特定のinterface typeを満足しているか調べるには,調べたい変数をinterface{}にキャストしてtype assertionを使う (type assertionできるのは interface typeのみ)
http://play.golang.org/p/brB8FOHjgc

package main

import "fmt"

type Foo interface {
	Foo() string
}

type Bar struct{}

type Boo struct{}

func (b *Bar) Foo() string {
	return "Bar: Foo()"
}

func (b *Bar) Bar() string {
	return "Bar: Bar()"
}

func main() {
	var b *Bar = &Bar{}
	if f, ok := interface{}(b).(Foo); ok {
		fmt.Println(f.Foo())
	}
}
Bar: Foo()


・type assertionするのにswitch文が使える
http://golang.org/ref/spec#Switch_statements
http://play.golang.org/p/owDgNUWLGC

package main

import "fmt"

type Foo interface {
	Foo() string
}

type Bar struct{}

type Boo struct{}

func (b *Bar) Foo() string {
	return "Bar: Foo()"
}

func (b *Bar) Bar() string {
	return "Bar: Bar()"
}

func (b *Boo) Foo() string {
	return "Boo: Foo()"
}

func (b *Boo) Boo() string {
	return "Boo: Boo()"
}

func main() {
	var f Foo = &Bar{}
	switch f.(type) {
		case (*Bar) : {
			fmt.Println(f.(*Bar).Bar())
		}
		case (*Boo) : {
			fmt.Println(f.(*Boo).Boo())
		}
		default :{
			fmt.Println("unkown type")
		}
	}
}
Bar: Bar()


まとめ: 普通に公式のspecが分かりやすい