简体   繁体   English

Golang:在哪里调用接口方法?

[英]Golang: Where is an Interface method called?

I don't understand at which point an Interface method is being called. 我不明白在哪一点上调用了Interface方法。 I'm looking at the following example from the Go Tour : 我正在看Go Go中的以下示例:

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)
}

Problem: 问题:

I understand that the func (p Person) receives the String() method and that it returns the string I want to display. 我知道func (p Person)接收String()方法并返回我想要显示的string But the fmt.Println in the main() method has to call String() at some point, right? 但是main()方法中的fmt.Println必须在某个时刻调用String() ,对吗?

I had a look at the source of fmt in godoc , but I still cannot figure it out! 我看过godocfmt 来源 ,但我仍然无法弄明白!

Another example: 另一个例子:

If I add my own interface, lets say Stringer2 with a method called String2() and then create a func (p Person) String2() {....} . 如果我添加自己的接口,让我们说Stringer2使用一个名为String2()的方法,然后创建一个func (p Person) String2() {....} How does String() get executed by fmt.Println , but String2() not? String()如何被fmt.Println执行,但fmt.Println String2()不是?

The value is passed to Println as an interface{} , and is checked if it satisfies the fmt.Stringer interface via a "type assertion" often in the form of a "type switch" . 该值被传递到Println作为interface{}并且如果它满足检验fmt.Stringer经由接口“类型断言”通常以的形式“型开关”

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())
    }
}

However, other methods may take precedence when printing from the fmt package. 但是,从fmt软件包打印时,其他方法可能优先。 There are first checks for fmt.Formatter , fmt.GoStringer , error , and then finally fmt.Stringer . 首先检查fmt.Formatterfmt.GoStringererror ,然后最后fmt.Stringer

The fmt package works with the interfaces it defines, in this case Stringer . fmt包与它定义的接口一起使用,在本例中为Stringer It does not know of interfaces defined by you so it wouldn't know to call String2() even if you pass it a type that meets the Stringer2 interface. 它不知道你定义的接口,所以即使你传递一个符合Stringer2接口的类型,它也不会知道调用String2()

Interfaces are a way to have common behavior between types. 接口是在类型之间具有共同行为的一种方式。 So if you create a function Foo(s Stringer2) , Foo can simply call s.String2() confident that anything passed into it will have the function String2() . 所以如果你创建一个函数Foo(s Stringer2) ,Foo可以简单地调用s.String2()确信传入它的任何东西都有函数String2()

To go a bit deeper, fmt.Println takes interface{} types and then uses reflection to check if the given argument meets the Stringer interface to then call String() . 为了更深入, fmt.Println采用interface{}类型,然后使用反射来检查给定的参数是否符合Stringer接口,然后调用String()

Make sense? 合理?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM