为什么以下Go程序需要函数的名称为String()而不是其他任何东西?

时间:2017-09-11 03:58:22

标签: go

我正在关注一本显示以下示例的书。

package main

import (
    "fmt"
)

const (
    KB = 1024
    MB = 1048576          //KB * 1024
    GB = 1073741824       //MB * 1024
    TB = 1099511627776    //GB * 1024
    PB = 1125899906842624 //TB * 1024
)

type ByteSize float64

func (b ByteSize) String() string {
    switch {
    case b >= PB:
        return "Very Big"
    case b >= TB:
        return fmt.Sprintf("%.2fTB", b/TB)
    case b >= GB:
        return fmt.Sprintf("%.2fGB", b/GB)
    case b >= MB:
        return fmt.Sprintf("%.2fMB", b/MB)
    case b >= KB:
        return fmt.Sprintf("%.2fKB", b/KB)
    }
    return fmt.Sprintf("%dB", b)
}

func main() {
    fmt.Println(ByteSize(2048))
    fmt.Println(ByteSize(3292528.64))
}

当我运行这个程序时,它给我以下输出(以人类可读的数据大小单位)。

2.00KB
3.14MB

但是当我将名为String()的函数的名称更改为其他任何名称时,或者如果我将字符串中的S小写,它会给我以下输出。

2048
3.29252864e+06

背后的原因是什么?是否有一些String()函数附加到某个接口,我们的ByteSize类型是否满足该接口?我的意思是什么鬼?

3 个答案:

答案 0 :(得分:4)

你的最后一句话是完全正确的。在Go中,您可以满足您甚至不知道存在的接口。您可以为其他人的功能编写新的界面。他们的代码不必编写“实现”或派生或任何东西。它完全基于函数名称,并具有匹配的参数和返回值列表。

答案 1 :(得分:2)

当您定义一个名为String且没有参数返回字符串的方法时,您可以实现Stringer接口,此处记录在此:https://golang.org/pkg/fmt/#Stringer

答案 2 :(得分:1)

该示例非常类似于Go Authors的“Effective Go”中的示例,以及那里描述的String()方法的含义。

  

将String等方法附加到任何用户定义类型的功能   使任意值可以格式化自己   自动进行打印。虽然你会看到最常用的   对于结构,这种技术对于标量类型也很有用   浮点类型,如ByteSize。

请参阅:https://golang.org/doc/effective_go.html#constants