在fmt.Println的实现中,好像并没有涉及String() string方法的实现

再问一个问题: 在fmt.Println的实现中,好像并没有涉及String() string方法的实现,但程序是可以正常调用Printfln的, 下面的程序是实现了String() string方法的,

func (part Part) String() string {
     return fmt.Sprintf("%s: %s", part.Name, part.Description)

程序的输出发生了改变。 我的问题是: fmt.Println和String() string这个方法没什么关系,那为什么自己实现了String() string这个方法后,又会影响fmt.Println的输出呢?

package main

import "fmt"

type Part struct {
    Name        string
    Description string
    NeedsSpare  bool
}

func (parts Parts) Spares() (spares Parts) {
    for _, part := range parts {
        if part.NeedsSpare {
            spares = append(spares, part)
        }
    }
    return spares
}

type Bicycle struct {
    Size string
    Parts
}

type Parts []Part

var (
    RoadBikeParts = Parts{
        {"chain", "10-speed", true},
        {"tire_size", "23", true},
        {"tape_color", "red", true},
    }

    MountainBikeParts = Parts{
        {"chain", "10-speed", true},
        {"tire_size", "2.1", true},
        {"front_shock", "Manitou", false},
        {"rear_shock", "Fox", true},
    }

    RecumbentBikeParts = Parts{
        {"chain", "9-speed", true},
        {"tire_size", "28", true},
        {"flag", "tall and orange", true},
    }
)

func (part Part) String() string {
    return fmt.Sprintf("%s: %s", part.Name, part.Description)
}
func main() {
    roadBike := Bicycle{Size: "L", Parts: RoadBikeParts}
    mountainBike := Bicycle{Size: "L", Parts: MountainBikeParts}
    recumbentBike := Bicycle{Size: "L", Parts: RecumbentBikeParts}

    fmt.Println(roadBike.Spares())
    fmt.Println(mountainBike.Spares())
    fmt.Println(recumbentBike.Spares())

    comboParts := Parts{}
    comboParts = append(comboParts, mountainBike.Parts...)
    comboParts = append(comboParts, roadBike.Parts...)
    comboParts = append(comboParts, recumbentBike.Parts...)

    fmt.Println(len(comboParts), comboParts[9:])
    fmt.Println(comboParts.Spares())
}

共 3 个回复


jimmykuu

你说的是调用的意思,实现是另一个意思。

如何查找给你个思路:看源代码,找到fmt.Println的实现:

func Println(a ...interface{}) (n int, err error) {
    return Fprintln(os.Stdout, a...)
}

再找Fprintln的实现:

func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
    p := newPrinter()
    p.doPrint(a, true, true)
    n64, err := w.Write(p.buf)
    p.free()
    return int(n64), err
}

看到doPrint方法了吧,一层层找下去,最后你会找到printReflectValue这个方法,要看懂代码,需要了解reflect的知识。

# 0

gogo

非常感谢,等会仔细去分析下。

# 1

sunfmin

直接fmt包下全文搜Stringer, print.go的701行

# 2