为什么不按名称调用此String()方法

时间:2019-01-22 11:53:11

标签: go

请考虑以下代码。第一个功能是MessageStr类型的接收器方法。为什么fmt.Println(msgstr)执行第一个方法而不将方法称为fmt.Println(msgstr.String())。也是为什么fmt.Println(msgint32)不执行第二种方法的原因。

package main

import (
    "fmt"
)

type MessageStr string
type MessageInt32 int32

func (msgs MessageStr) String() string {
    return string("<<" + msgs + ">>")
}

func (msgi MessageInt32) Int32() int32 {
    return int32(msgi * 2)
}

func main() {

    msgstr := MessageStr("Mastering Go")
    // why this outputs <<Mastering Go>>
    // without calling the String() method
    fmt.Println(msgstr)


    msgint32 := MessageInt32(11)
    // why this doesn't output 11*2 = 22
    fmt.Println(msgint32)

    fmt.Println(msgint32.Int32())

}

1 个答案:

答案 0 :(得分:3)

调用fmt.Println时,它会期望一个实现Stringer接口的对象。 documented如下:

  

如果操作数实现String()字符串方法,则该方法将是   调用以将对象转换为字符串,然后将其转换为   根据动词要求的格式设置(如果有)

fmt包还声明了Stringer接口:

type Stringer interface {
    String() string
}

此类对象必须具有不带参数且返回String()的{​​{1}}方法。 string然后调用fmt.Println方法。这使我们可以为自定义类型定义如何将其打印出来。例如:

String

将打印出

package main

import "fmt"

type Person struct {
    name string
    age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%s<%d>", p.name, p.age)
}

func main() {
    p := Person{name: "Joe", age: 39}
    fmt.Println(p)
}

因为我们已经定制了Joe<39> 对象被转换为字符串的方式。详细信息:


如果您对如何在Person包中实际发生这种情况的机制感兴趣,请查看fmt中的handleMethods方法。