duannima8347
duannima8347
2017-09-11 03:58
浏览 31
已采纳

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

I'm following a book which shows the following example.

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

When I run this program it gives me the following output (in human readable data size units).

2.00KB
3.14MB

But when I change the name of the function called String() to anything else, or if I lower-case the S in String, it gives me the following output.

2048
3.29252864e+06

What is the reason behind that? Is there some String() function attached to some interface and our ByteSize type satisfies that interface? I mean what the hell?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • ds000001
    ds000001 2017-09-11 04:00
    已采纳

    When you define a method named String with no parameters returning a string, you implement the Stringer interface, which is documented here: https://golang.org/pkg/fmt/#Stringer.

    点赞 评论
  • dongtang1944
    dongtang1944 2017-09-11 04:06

    Your last sentence is exactly right. In Go, you can satisfy interfaces you didn't even know existed. And you can write new interfaces for other people's functions. Their code does not have to write "implement" or derive or anything. It is entirely based on the function name and having a matching argument and return value list.

    点赞 评论
  • dousha1831
    dousha1831 2017-09-11 07:50

    The example is very similar to an example in "Effective Go" by the Go Authors, and the meaning of the String() method described there.

    The ability to attach a method such as String to any user-defined type makes it possible for arbitrary values to format themselves automatically for printing. Although you'll see it most often applied to structs, this technique is also useful for scalar types such as floating-point types like ByteSize.

    See: https://golang.org/doc/effective_go.html#constants

    点赞 评论