围棋之旅:了解纵梁练习

Tour of Go: Understanding the stringers exercise

我在做 this exercise on stringers

问题:使 IPAddr 类型的工具 fmt.Stringer 将地址打印为点分四边形。例如,IPAddr{1, 2, 3, 4} 应打印为 "1.2.3.4"

起始代码:

package main

import "fmt"

type IPAddr [4]byte

// TODO: Add a "String() string" method to IPAddr.

func main() {
    hosts := map[string]IPAddr{
        "loopback":  {127, 0, 0, 1},
        "googleDNS": {8, 8, 8, 8},
    }
    for name, ip := range hosts {
        fmt.Printf("%v: %v\n", name, ip)
    }
}

这是我的代码:

func (addr IPAddr) String() string {
    return fmt.Sprintf("%v.%v.%v.%v", addr[0], addr[1], addr[2], addr[3])
}

而且成功了!但我不明白为什么。我发现我不必明确定义 Stringer 接口,因为它包含在 fmt 中,但是我的代码在 main() 函数中的什么地方被使用了?它是否会自动 运行 它找到任何 IPAddr 类型的数据,这就是为什么地图在我不做任何事情的情况下被修改的原因?这是我的第一个基于编译器的语言(我知道一些 Python 和 JavaScript),所以我不知道这个概念是否与其他语言相似。

main 使用 fmt.Printf 打印 IP 地址,如果类型实现 Stringer 接口,则使用 String() 方法。由于您为该类型声明了 String() string 方法,因此 IPAddr 实现了 Stringer 接口。

您正在寻找的概念称为“Duck Typing”。无需将类型声明为实现接口。如果一个类型具有与接口相同的方法,则该类型实现该接口