Interface(実装を持たない抽象型であり、メソッドのシグネチャを定義することで、他の型がそのインターフェースを実装できる) と Struct(type指定されたフィールドの集合であり、データの構造を表現する)
k8sでよく使われる
Reconcilerのinterfaceで、ReconcileメソッドがContextとRequestを引数に取り、Resultとerrorを返す。
type Reconciler interface {
Reconcile(context.Context, Request) (Result, error)
}
Structの簡単な例
Personというstructを宣言
type Person struct {
Id int
Name string
}
structにメソッドを追加 ( `func レシーバ メソッド名(引数リスト) 戻り値リスト {}` )
# レシーバ(変数:p 型:Person)
func (p Person) GetName() string {
return p.Name
}
# nameを引数として取って、p.Nameを更新する
# 「*」が付いているのはポインタレシーバ(フィールドを変更する)
# 大きなデータ構造だとコピーを作るのはメモリを消費するのでポインタを利用し、直接操作するのが効率的
func (p *Person) SetNmae(name string) {
p.Name = name
}
structを使っていく
# インスタンスを初期化
# := を使う時はstructのリテラル{}を使う
func main() {
p := Person{Id: 721, Name: "harukin"}
fmt.Println(p) // {721 harukin}
p.SetName("uejima")
fmt.Println(p.GetName) // uejima
}
Embedding(継承みたいなものと理解している)
# Personが持っているメソッドやフィールドをそのまま使える
type Hoge struct {
Person
OtherField string
}
main関数を変更
func main() {
p := Person{Id: 721, Name: "harukin"}
h := Hoge{Person: p}
fmt.Printf("id: %d, name: %s\n", h.Id, h.Name) // {id: 721, name: harukin}
h = Hoge{Person{Id: 721, Name:"uejima"},"Other"}
p.SetName("Uejima")
fmt.Println(h.GetName) // uejima
}
Interfaceの簡単な例
Objectというinterfaceを宣言
type Object interface {
GetName() string
}
PersonもHogeもGetNameという関数を持ち、オブジェクトのInterfaceを実装している
func main() {
p := Person{Id: 721, Name: "harukin"}
printObjectName(&p) // harukin
h := Hoge{Person: p}
printObjectName(&h) // harukin
h = Hoge{Person{Id: 721, Name:"uejima"},"Other"}
printObjectName(&h) // uejima
}
// Objectインターフェースを受け取る
// GetNameメソッドを呼び出してオブジェクトの名前を出力
func printObjectName (obj Object) {
fmt.Println(obj. GetName())
}
最初よりは理解ができている。はず。