2015-12-11 6 views
7

私は遅いのを許してください、しかし、私はインターフェイスメソッドが呼び出されているときは分かりません。私は行くツアーからこの例で探しています:Golang:Interfaceメソッドはどこにありますか?

package main 

import "fmt" 

type Person struct { 
    Name string 
    Age int 
} 

func (p Person) String() string { 
    return fmt.Sprintf("%v (%v years)", p.Name, p.Age) 
} 

func main() { 
    a := Person{"Arthur Dent", 42} 
    z := Person{"Zaphod Beeblebrox", 9001} 
    fmt.Println(a, z) 
} 

私はFUNC(Pの人が)文字列()メソッドを受け取り、それは私が表示したい文字列を返すことを理解しています。

しかし、どこかメインでfmt.Printlnは()、右、何とかいくつかの点で文字列を()を呼び出す必要があり?

私はgodocにFMTのソースを見ていたが、私はまだそれを把握することはできません!

私は自分のインタフェースを追加した場合、方法文字列2とStringer2を(言うことができます)と私は、文字列は()で実行を受けるんどのようにして、FUNC(Pパーソン)文字列2(){....}を作成しますfmt.Printlnではなく、String2()?

私は自分自身を混乱させる、私は知っている!

+1

これは、パッケージ全体で実際にprint.goの16の異なる場所に呼び出されます。私はあまり心配しません。特定の例のためにどのように印刷するかを試してみると、そのパッケージはすべてのタイプの印刷を処理します...それは、多くの異なるコードパスを持っています。 – evanmcdonnal

+0

私はこれに挑戦しようとしていましたが、Evanは正しいです。あなたは正しいですが、Stringはスタック内のどこかで呼び出され、インターフェイスはメソッド名に基づいて暗黙的に満たされるため動作します。 – saarrrr

答えて

12

interface{}としてPrintlnに渡され、それはしばしば"type switch"の形態で"type assertion"介しfmt.Stringerインタフェースを満たす場合チェックされます。 fmtパッケージから印刷するとき

func IsStringer(i interface{}) { 
    switch s := i.(type) { 
    case fmt.Stringer: 
     fmt.Println("Person a has a String() method") 
     fmt.Println(s.String()) 
    default: 
     fmt.Println("not a stringer") 
    } 

    // OR for a single type 

    if s, ok := i.(fmt.Stringer); ok { 
     fmt.Println("Person a has a String() method") 
     fmt.Println(s.String()) 
    } 
} 

しかし、他の方法が優先されますがあります。 fmt.Formatterfmt.GoStringererror、最後にfmt.Stringerの最初のチェックがあります。

1

fmtパッケージは、この場合Stringerで、それは定義インタフェースで動作します。それはあなたが定義したインターフェースを知らないので、String2()に、Stringer2インターフェースを満たすタイプを渡したとしても、それを呼び出すことを知らないでしょう。

インターフェイスは、種類間で共通の動作を持つ方法です。したがって、関数Foo(s Stringer2)を作成した場合、Fooは単にs.String2()を呼び出して、渡されたものが関数String2()を持つことを確信できます。少し深く行くために

fmt.Printlninterface{}種類を取り、その後、与えられた引数が、その後String()を呼び出すStringerインタフェースを満たしているかどうかをチェックするためにリフレクションを使用しています。

意味がありますか?

関連する問題