Go ã® interface è¨è¨
history
- 13/3/31
- Tag ã«ã¤ãã¦è¿½å
intro
Go ã触ã£ã¦ã¦ interface ãç¨ããè¨è¨ãã¾ã ã¾ã ããããã£ã¦ãªãã£ãã®ã§ãä¸æ¦ã¾ã¨ãããã¨ã«ãã¾ããã
Go ã«ã¯æ示çãªç¶æ¿ã®æ©è½ã¯ç¡ãã interface ãä¾ãã° Java ã®ããã¨ã¯ããªãæ¯è²ãéãã®ã§ã(Class ã§ã¯ãªã) Struct ã®è¨è¨ã«çµæ§çãããã¨æãã¾ãã
Go ã® interface ã¯è¨èªè¨è¨çã«ãããªãå°ã£ã¦ãã¦ã Go ã¨ããè¨èªãå¼·ãç¹å¾´ä»ãã¦ããã¨åæã«ã Go è¨èªèªä½ã®éçºè ãã¡ããã®æ©è½ãããªãéè¦è¦ãã¦ãã¾ãã
ä¾ãã°ã Go ã®éçºè
ã®ä¸äººã§ãã Russ Cox æ°ã«ããã°
Go's interfacesâstatic, checked at compile time, dynamic when asked forâare,
http://research.swtch.com/interfaces
for me, the most exciting part of Go from a language design point of view. If
I could export one feature of Go into other languages, it would be
interfaces.
ã¨ã®ãã¨ã
ãInterface ãå¶ããã®ã¯ Go ãå¶ãã
ãªã®ãããããªããã¨æãã¾ããã®æ©è½ã使ãæ¹ã®è¦ç¹ããã¾ã¨ãã¦ã¿ã¾ããã
(ã¾ããåã«ã¤ãã¯ã®æ¯ãç©ãå§ããããéåé ãã¾ã§æ¥ã¦ãã¾ã£ãã¨ãã話ãã)
ã½ã¼ã¹
ä»åã®è¨äºã®ãã¨ã«ãªãã½ã¼ã¹ã¯ããã¡ãã«ããã¾ãã
https://gist.github.com/Jxck/5237600
Basic
ã¾ãã¯ãåºæ¬ç㪠Struct (Class çãªãã®) ã¨ãã®ã¡ã½ããå®ç¾©ããã
(æ¬å½ã¯ä¸è¨ã®ä¾ã¯ String() ãå®è£
ããã®ãæ£è§£ã ãã©ããã¯å¥ã§)
// åºæ¬ç㪠Struct type Point struct { X int Y int } // Struct ã®ã¡ã½ãã func (p Point) Coordinate() string { // p ãã¬ã·ã¼ã return fmt.Sprintf("(%d, %d)", p.X, p.Y) } func main1() { var a Point = Point{2, 3} fmt.Println(a.Coordinate()) // (2, 3) }
æ¢åã®åãæ¡å¼µã§ãã¾ãã
// æ¢åã®åãå ã«ããç¬èªã®åãå®ç¾©ã§ããã type trimmedString string // ããã«ã¡ã½ããã追å ã§ããã func (t trimmedString) trim() trimmedString { return t[:3] } func main2() { var t trimmedString = "abcdefg" fmt.Println(t.trim()) // åå¤æ var s string = string(t) // åãå¤æããã®ã§ã trim() ã¯ç¡ã // fmt.Println(s.trim()) fmt.Println(s) }
ãã®è¾ºã¯ tour of go ã§ãããªãã¿ã§ãã
interface
Go ã® interface ã®å®ç¾©ã®å
容ã¯ãåãªãã¡ã½ãããªã¹ãã§ãã
ãªã¹ãä¸ã®ã¡ã½ãããå
¨ã¦å®è£
ãã¦ããã°ããã® Interface ãæºãã(satisfy) ã¨ã¿ãªããã¾ãã
Java ã§ã¯å®è£ (implements) ã¨å®£è¨ããã¾ãããããããæ示çãªå®£è¨ã¯ãªãã®ã Goã®ç¹å¾´ã§ãã
// Interface ãå®£è¨ type Accessor interface { GetText() string SetText(string) } // Accessor ãæºããå®è£ // Interface ã®æã¤ã¡ã½ãã群ãå®è£ ãã¦ããã°ã // Interface ãæºãã(satisfy) ã¨ãããã // æ示çãªå®£è¨ã¯å¿ è¦ãªããå®è£ ã¨å®å ¨ã«åé¢ãã¦ããã type Document struct { text string } func (d *Document) GetText() string { return d.text } func (d *Document) SetText(text string) { d.text = text } func main3() { // Document ã®ã¤ã³ã¹ã¿ã³ã¹ãç´æ¥å¤æ´ãã¦ã // å¤æ¸¡ãã«ãªã£ã¦ãã¾ãã®ã§ // ãã¤ã³ã¿ãä½¿ç¨ var doc *Document = &Document{} doc.SetText("document") fmt.Println(doc.GetText()) // Accessor Interface ãå®è£ ãã¦ããã®ã§ // Accessor åã«ä»£å ¥å¯è½ var acsr Accessor = &Document{} acsr.SetText("accessor") fmt.Println(acsr.GetText()) }
mixin
å¥ã®åãå®ç¾©ã«å«ãã¨ãå«ãã åã®ã¡ã½ãããå®ç¾©ãããç¶æ
ã«ãªãã¾ãã
ããã¯ç¶æ¿ã¨ãããã㯠mixin ã®ã¤ã¡ã¼ã¸ã§ããã
ãã®å ´åãç¶æ¿(å¼ãç¶ãã ãç¨åº¦ã®æå³ã§ã®)ãããã¡ã½ããå
ã®ã¬ã·ã¼ãã®æåã«æ³¨æã§ãã
type Page struct { Document // å¿ååãå«ãã¨ããã®åã®ã¡ã½ãããç¶æ¿(ã¨ããã mixin)ããã Page int } func main4() { // Page 㯠Document ãç¶æ¿ãã¦ãã // Accessor Interface ãæºããã // ãã®å ´åä»£å ¥å¯è½ var acsr Accessor = &Page{} // ãã®å¤ã¯ acsr.Document.text ã«è¨å®ããã¦ãã // acsr ã®æ§é ä½ãã¬ã·ã¼ãã«ãªã£ã¦ããããã§ã¯ãªãã¨ããã㨠acsr.SetText("page") fmt.Println(acsr.GetText()) // Document 㨠Page ã®éã«ä»£å ¥å¯è½ãªé¢ä¿ã¯ç¡ã // var page Page = Document{} // var doc Document = Page{} }
Duck Typing
ãã¢ãã«ã®ããã«é³´ããªããããã¯ã¢ãã«ãã
åçãªåä»ãè¨èªã§ã¯ããé³´ãããã¨ãã§ãããã¯å®è¡æã«è©¦ãããäºãã¡ã½ããã®å
é ãªã©ã§èª¿ã¹ãå¿
è¦ãããã¾ãã
Go ã®å ´åã¯ãé³´ãããã¨èªä½ã interface ã§å®ç¾©ããã©ã³ã¿ã¤ã ã§ã¯ãªãã³ã³ãã¤ã«æã«ãã§ãã¯ã§ãã¾ãã
ã¡ã½ããã®å¼æ°ã« Interface åãæå®ãã¦ãã³ã³ãã¤ã«ãéã£ãæç¹ã§ã渡ãããå¤ã¯ã¢ãã«ã®ããã«é³´ããã¨ãä¿è¨¼ãããããã§ãã
/* Duck Typing Accessor ãæºããã¦ããã°ã Get, Set ã§ããã¨ããä¾ã */ func SetAndGet(acsr Accessor) { acsr.SetText("accessor") fmt.Println(acsr.GetText()) } func main5() { // ã©ã¡ãã Accessor ã¨ãã¦æ¯ãèãã SetAndGet(&Page{}) SetAndGet(&Document{}) }
Override
Override ã¯ãã®ã¾ã¾ã
ç´°ãããã© int -> string ã®å¤æ㯠string(i) ã§ã¯ã§ããã strconv.Itoa ã使ãã
(ãã ã Overload ã¯ã§ããªãããã®è¾ºã¯ã©ãããã°ãããã ããããå¯å¤é·å¼æ°ããªï¼)
/* Override */ type ExtendedPage struct { Document Page int } // Document.GetText() ã®ãªã¼ãã¼ã©ã¤ã func (ep *ExtendedPage) GetText() string { // int -> string 㯠strconv.Itoa ä½¿ç¨ return strconv.Itoa(ep.Page) + " : " + ep.Document.GetText() } func main6() { // Accessor ãå®è£ ãã¦ãã var acsr Accessor = &ExtendedPage{ Document{}, 2, } acsr.SetText("page") fmt.Println(acsr.GetText()) // 2 : page }
Interface å
Interface åã¯ã¡ã½ãããæããªã Interface ã§ãã
ã¤ã¾ããã¡ã½ãããæããªã struct ãå«ãã¦ãå
¨ã¦ã® struct 㯠Interface åãæºããã¨è¨ãã¾ãã
ä¾ãã°ãä¸è¨ã®ã¡ã½ããã¯å ¨ã¦ã®åã®å¤ãåãåããã¨ãã§ãã¾ãã
func f(v interface {}) { // v }
ããããããã§éè¦ãªã®ã¯ v ã®å㯠interface{} åã§ããã¨ãããã¨ã
Go ã® runtime ã§ã¯ãå
¨ã¦ã®å¤ã¯å¿
ãä¸ã¤ã®åãæã¤ã®ã§ãåãä¸å®ã¨ãã£ããã¨ã¯ãªããã¡ã½ããã®å¼æ°ãªã©ã§ã¯å¯è½ã§ããã°åã®å¤æãè¡ããã¾ãã
ä¸è¨ f() ã¯å
¨ã¦ã®å¤ã interface{} åã«å¤æãã¾ãã
interface {} åã® struct ããä»»æã® type ã§ãããã¨ã¯ãåã¢ãµã¼ã·ã§ã³ã¨ããæ©è½ãç¨ãã¦è¡ãã¾ãã
åã¢ãµã¼ã·ã§ã³ã®ã·ã°ããã£ã¯ä»¥ä¸ã
e, ok := v.(type) // v ã type ãæºãããã調ã¹ã
// Interface å // Get() ããããã調ã¹ã // er ãä»ããå½åãæ £ç¿ type Getter interface { GetText() string } func dynamicIf(v interface{}) string { // v 㯠Interface å var result string g, ok := v.(Getter) // v ã Get() ãå®è£ ãã¦ããã調ã¹ã if ok { result = g.GetText() } else { result = "not implemented" } return result } func dynamicSwitch(v interface{}) string { // v 㯠Interface å var result string // v ãå®è£ ãã¦ããåã§ã¹ã¤ãããã switch checked := v.(type) { case Getter: result = checked.GetText() case string: result = "not implemented" } return result } func main7() { var ep *ExtendedPage = &ExtendedPage{ Document{}, 3, } ep.SetText("page") // do 㯠Interface åãåã // ã¸ã§ããªã¯ã¹çãªãã¨ãã§ãã fmt.Println(dynamicIf(ep)) // 3 : page fmt.Println(dynamicIf("string")) // not implemented // åã¹ã¤ããã使ãå ´å fmt.Println(dynamicSwitch(ep)) // 3 : page fmt.Println(dynamicSwitch("string")) // not implemented }
Generics
Go の wikiã§ç´¹ä»ããã¦ããæ¹æ³ã§ãã
interface{} ããã®ã¾ã¾ä½¿ããã Any åãå®ç¾©ãã¦ç½®ãæãã¦ããã ãã§ããããããªãå¾ã§ Any åã®å®ç¾©ãããããã®ã§ããè¯ãããã§ãã
ããã«ããã Generics çãªãã¨ãã§ãã¾ãã(Java ã® Generics ã¨ã¾ã§ã¯ããã¾ããã)
// å ¨ã¦ã®åã許容ããã¤ã³ã¿ãã§ã¼ã¹ã®ãããªãã®ãä½ã£ã¦ãã type Any interface{} // ã¸ã§ããªã¯ã¹ç㪠type GetValuer interface { GetValue() Any } // Any åã§å®è£ type Value struct { v Any } // GetValuer ãå®è£ func (v *Value) GetValue() Any { return v.v } func main8() { // ã¤ã³ã¿ãã§ã¼ã¹ã§åãåã var i GetValuer = &Value{10} var s GetValuer = &Value{"vvv"} // ã¤ã³ã¿ãã§ã¼ã¹åã®ã³ã¬ã¯ã·ã§ã³ã«æ ¼ç´ var values []GetValuer = []GetValuer{i, s} // ãããã GetValue() ã Any ã§å¼ã¹ã for _, val := range values { fmt.Println(val.GetValue()) } }
inerface ã®å®è£
interface ã®å¤ã¯äºã¤ã®ãã¤ã³ã¿ããæãã
- å ã«ãªãåã®ãã¡ã½ãããã¼ãã«
- å ã®å¤ãæã¤å¤
ãããããã£ã¦ããã°ãä¸è¨ãééã£ã¦ãããã¨ããããã
[]string ã®ã¡ã½ãããã¼ãã«ã¨å¤ã¯æã¦ããããã®ä¸ã®å¤ã interface ã«ã¯å¤æã§ããªãããã
åè http://golang.org/doc/faq#convert_slice_of_interface
func PrintAll(vals []interface{}) { for _, val := range vals { fmt.Println(val) } } func main9() { names := []string{"one", "two", "three"} // ããã¯ééã // PrintAll(names) // æ示çã«å¤æãå¿ è¦ vals := make([]interface{}, len(names)) for i, v := range names { vals[i] = v } PrintAll(vals) }
Interface ã®è¨è¨ä¾ 1 (interface{})
interface ã®è¨è¨ä¾ã¨ãã¦ãä¸è¨ã« 2 ã¤ã®ä¾ãããã®ã§ããããåç¨ãã¾ãã
http://jordanorelli.tumblr.com/post/32665860244/how-to-use-interfaces-in-go
1 ã¤ç®ã¯ Twitter API ã§åãåã£ã JSON å
ã®æ¥ä»ã®æååããã¼ã¹ããä¾ã§ãã
JSON ã®ãã¼ã¹èªä½ã¯ json.Unmarshal() ã§å¯è½ã§ãã
ãã¼ã¹å
ã®åã¨ã㦠map[string]interface{} ãç¨ããã°ã©ããªåã§ãã¨ãããããã¼ã¹å¯è½ã§ãã
// 1, twitter API ãã Time ã®ãã¼ã¹ /* Twitter ã® JSON ã map ã«ãã¼ã¹ããã twitter ã® JSON ã«ã¯ãæéã Ruby ãã©ã¼ãããã®æååã§æ ¼ç´ããã¦ããã®ã§ã ãããèæ ®ãã¦åãèããã "Thu May 31 00:00:01 +0000 2012" */ var JSONString = `{ "created_at": "Thu May 31 00:00:01 +0000 2012" } ` func main10() { // map ã¨ãã¦ã {string: interface{}} ã¨ãã¦ãã¾ãã° // value ããªãã§ãããã¼ã¹ã¯å¯è½ var parsedMap map[string]interface{} if err := json.Unmarshal([]byte(JSONString), &parsedMap); err != nil { panic(err) } fmt.Println(parsedMap) // map[created_at:Thu May 31 00:00:01 +0000 2012] for k, v := range parsedMap { fmt.Println(k, reflect.TypeOf(v)) // created_at string } }
Interface ã®è¨è¨ä¾ 1 (time.Time)
æ¬æ¥ Go ã® time.Time åã§ããã¨æã¾ããã®ã§ããã Ruby ã®æååãã©ã¼ããããtime.Time ã®æååã¨ããã©ã«ããã©ã¼ããããéãã¾ãã
ããã§ã time.Time ãå
ã«æ°ããªåãå®ç¾©ãã¾ãã
ã¾ãã JSON ã® Unmarshaller ã®ã¤ã³ã¿ãã§ã¼ã¹ã¯ä¸è¨ã®ããã«ãªã£ã¦ããã®ã§ãUnmershalJSON() ãå®è£ ããã°ã Unmarshaller ã¯æºãããã¾ãã
type Unmarshaler interface { UnmarshalJSON([]byte) error }
ãªãã¨ããã©ã«ã㧠time.RubyDate ãç¨æããã¦ããã®ã§ããã使ãã°çµããã§ãã
http://golang.org/pkg/time/#pkg-constants (ããã Battery Included !)
type Timestamp time.Time // Unmarshaller ãå®è£ func (t *Timestamp) UnmarshalJSON(b []byte) error { v, err := time.Parse(time.RubyDate, string(b[1:len(b)-1])) if err != nil { return err } *t = Timestamp(v) return nil } func main11() { var val map[string]Timestamp // å®ç¾©ããåã使ã if err := json.Unmarshal([]byte(JSONString), &val); err != nil { panic(err) } // ãã¼ã¹ããã¦ãããã¨ãç¢ºèª for k, v := range val { fmt.Println(k, time.Time(v), reflect.TypeOf(v)) // created_at 2012-05-31 00:00:01 +0000 +0000 main.Timestamp } }
Interface ã®è¨è¨ä¾ 2 (JSON Entity)
HTTP ãªã¯ã¨ã¹ããã JSON ãåå¾ãããªãã¸ã§ã¯ãã«ãã¼ã¹ããä¾ã§ãã
åç´ã«ã·ã°ããã£ãèããã¨ä»¥ä¸ã®ããã«ãªãã¾ãã
GetEntity(*http.Request) (interface{}, error)
ããã¯ãæ»ãå¤ã®æ¹ã«æ±ç¨æ§ãæããã¦ãã©ã®ãããªåã®ãã¼ã¿ãåãåºããããã«ãã¦ãã¾ãã
ããããããã ã¨æ»ãå¤ã¯æ¯ååå¤æããªãã¨ãããªããã Postel ã®æ³åã«åãã¾ãã
(ãéä¿¡ãããã®ã«é¢ãã¦ã¯å³å¯ã«ãåä¿¡ãããã®ã«é¢ãã¦ã¯å¯å®¹ã«ã)
ããããä¾ãã°åãåºãåã User ã¨ãã¦ä¸è¨ã®ããã«ã·ã°ããã£ãå¤æ´ããã¨ãåã®æ°ã ã GetXXXX ãå¿ è¦ã«ãªãã¾ãã
GetUser(*http.Request) (User, error)
ããã§ã¤ã³ã¿ãã§ã¼ã¹ãå°å ¥ãã¾ãã
ä¸è¨ã®ä¾ã¯ã http ã§ããã¨ã¡ãã£ã¨é¢åãªã®ã§ã JSON ãæååã¾ã§åãåºããã¨ä»®å®ãã¦ã JSON ããã¼ã¹ããä¾ã«ç½®ãæãã¦ãã¾ãã
(JSON ãããæ¹ã«å¿ãã¦éãå¤ãåãåºãä¾ã§ãããã¡ã½ããã®ä¸ãåãã«ãªã£ã¦ãã¾ã£ãã®ã§ãã¾ãè¯ãä¾ã§ã¯ãªããã©ãåå°½ããã®ã§ãã®ã¾ã¾ãã)
// ååããèªèº«ã®ãã¼ã¹å®è£ ãæã¦ã°ããã®ã§ããã®ã¡ã½ããã ãå®ç¾©ãã¦ããã type Entity interface { UnmarshallJSON([]byte) error } func GetEntity(b []byte, e Entity) error { // åå®è£ ã«å¦çãç§»è² return e.UnmarshallJSON(b) } // åãå®ç¾© // User ã«é¢ããå¿ è¦ãªãã¼ã¿ã ãåãããåç㪠type UserData struct { Id int Name string Time_Zone string Lang string } // *_count ã ãé©å½ã«åãããåç㪠type CountData struct { Followers_count int Friends_count int Listed_count int Favourites_count int Statuses_count int } // Entity ãå®è£ // ããã§ã¯ã json ã¢ã¸ã¥ã¼ã«ã«ãªããã ã㧠// åãå®è£ ã§ã§ãã¦ãã¾ã£ããã // æ¬æ¥ Entity ãã¨ã«éãå®è£ ã«ãªãã func (d *UserData) UnmarshallJSON(b []byte) error { err := json.Unmarshal(b, d) if err != nil { return err } return nil } func (d *CountData) UnmarshallJSON(b []byte) error { err := json.Unmarshal(b, d) if err != nil { return err } return nil } func main12() { // 対象㮠JSON æåå EntityString := `{ "id":51442629, "name":"Jxck", "followers_count":1620, "friends_count":617, "listed_count":204, "favourites_count":2895, "time_zone":"Tokyo", "statuses_count":17387, "lang":"ja" }` userData := &UserData{} countData := &CountData{} GetEntity([]byte(EntityString), userData) GetEntity([]byte(EntityString), countData) fmt.Println(*userData) // {51442629 Jxck Tokyo ja} fmt.Println(*countData) // {1620 617 204 2895 17387} }
Tag
ブコメで指摘されてåãã¦ç¥ã£ãã®ã§ããã Struct ã«ã¯ Tag ãä»ãããã¨ãã§ãã¾ãã
ãã®ã¿ã°ã¯ã reflect ã¢ã¸ã¥ã¼ã«ã使ã£ã¦ããã¢ã¯ã»ã¹ãããã¨ãã§ãã Struct ã«å¯¾ããã¡ã¿æ
å ±ã®ãããªä½¿ãæ¹ãããããã§ãã
ã¾ããã¿ã°ã¯ä»¥ä¸ã®ããã« Struct ãã£ã¼ã«ãã®åã®æ¬¡ã«è¨è¿°ãã reflect ã§åãåºããã¨ãã§ãã¾ãã
// ã¿ã°ä»ãã® Struct ãå®ç¾© type TaggedStruct struct { field string `tag:"tag1"` } func main13() { // reflect ã§ã¿ã°ãåå¾ var ts = TaggedStruct{} var t reflect.Type = reflect.TypeOf(ts) var f reflect.StructField = t.Field(0) var tag reflect.StructTag = f.Tag var val string = tag.Get("json") fmt.Println(tag, val) // json:"emp_name" emp_name }
ç¾å¨æ¨æºã©ã¤ãã©ãªã§ Tag ã使ããã¦ããã®ã¯ encoding/json 㨠encoding/xml ã ãã®ããã§ãã
ä¾ãã° json ã§ã¯ã JSON ã®ãã¼å㨠Struct ã®ãã£ã¼ã«ãåãåãã§ããã°ãã®ã¾ã¾ Unmarshal å¯è½ã§ãããããäºã¤ãéã£ãå ´åã¯ãå¤æå
ã® Struct ã¨ã®ãã£ã¼ã«ãã®ãããã³ã°ã `json:"fieldname"` ã¨ããå½¢å¼ã§è¨è¿°ãããã¨ã§è§£æ±ºã§ãã¾ãã
// JSON ããããã³ã°ããããã« // ãã¼åã®ã¿ã°ä»ãã¤ãã Struct ãå®ç¾© type Employee struct { Name string `json:"emp_name"` Email string `json:"emp_email"` Dept string `json:"dept"` } func main14() { // ãã£ã¼ã«ãåã Struct ã® Filed åã¨éã JSON ã // json:"fieldname" ã®å½¢ã§ã¿ã°ãä»ãã¦ããã®ã§ // ãããã³ã°ãããã¨ãã§ããã var jsonString = []byte(` { "emp_name": "john", "emp_email" :"[email protected]", "dept" :"HR" }`) var john Employee err := json.Unmarshal(jsonString, &john) if err != nil { fmt.Println("error:", err) } fmt.Printf("%+v\n", john) // {Name:john Email:[email protected] Dept:HR} }
Wrap Up
ã¨ãããã¨ã§ãæµ ãã¨ããã§ãã interface ã®ä½¿ãæ¹ã¨åºæ¬çãªä½¿ãæ¹ãã¾ã¨ãã¾ããã
ä»ååèã«ããè³æã«ã¯ Go ã® interface ããã®ä¸ã® C++ ã®ã¬ã¤ã¤ã§ã©ããã£ãæ§é ã«ãªã£ã¦ããããªã©ãè¼ã£ã¦ããã®ã§ãä»åº¦ã¯ãã®è¾ºã¾ã§è¸ã¿è¾¼ãã§ã¾ã¨ãããã¨æãã¾ãã
ããããæ
£ããªã㨠Go ã§ã® interface è¨è¨ã¯æ
£ããªãã¨é£ããã§ããããããã§ããªãã¨ä»ä½ã£ã¦ããã®ãã¾ã¨ãã«çµããªãã®ã§ãæãè¯ããææ¬ã§ãããæ¨æºã©ã¤ãã©ãªãèªã¿ãªããåå¼·ãã¦ããããã¨ããã§ãã
åè
- GoForCPPProgrammers - go-wiki - Go for C++ Programmers - Go Language Community Wiki - Google Project Hosting
- jordan orelli
- research!rsc: Go Data Structures: Interfaces
- Airs – Ian Lance Taylor » Go Interfaces
- How to determine an interface{} value's "real" type? - Stack Overflow
- Goのinterface - はてなかよっ!
- Google Go! A look behind the scenes