Golang中如何通过String()方法改变Println的输出结果

Golang中如何通过String()方法改变Println的输出结果 我正在学习由Todd Mcleod在Udemy上教授的Go语言课程。

Todd使用了来自godoc.org/sort的代码,该代码位于sort包页面的示例链接(https://godoc.org/sort#ex-package)下。

我无法理解为什么String()函数会改变Println的输出,尽管我们并没有调用它。

2 回复

根据文档

如果格式(对于 Println 等函数隐式为 %v)对字符串有效(%s %q %v %x %X),则适用以下两条规则:

  1. 如果操作数实现了 error 接口,则将调用 Error 方法来将对象转换为字符串,然后根据动词(如果有)的要求进行格式化。
  2. 如果操作数实现了 String() string 方法,则将调用该方法来将对象转换为字符串,然后根据动词(如果有)的要求进行格式化。

更多关于Golang中如何通过String()方法改变Println的输出结果的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,当使用fmt.Println打印一个值时,如果该值实现了String() string方法,fmt包会自动调用它来获取字符串表示。这是Go语言中接口的隐式实现机制。

示例代码:

package main

import (
	"fmt"
	"sort"
)

type Person struct {
	Name string
	Age  int
}

// 实现String()方法
func (p Person) String() string {
	return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

func main() {
	people := []Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}

	fmt.Println(people) // 这里会自动调用每个Person的String()方法

	sort.Slice(people, func(i, j int) bool {
		return people[i].Age < people[j].Age
	})

	fmt.Println(people) // 排序后再次打印
}

输出结果:

[Bob: 31 John: 42 Michael: 17 Jenny: 26]
[Michael: 17 Jenny: 26 Bob: 31 John: 42]

在sort包的示例中,Planet类型实现了String()方法:

func (p Planet) String() string {
    return fmt.Sprintf("%s: %.2f", p.name, p.mass)
}

当执行fmt.Println(planets)时,fmt包会检查Planet类型是否实现了Stringer接口(该接口只包含String() string方法)。由于Planet实现了这个方法,fmt.Println就会调用它来获取每个元素的字符串表示,而不是使用默认的格式化输出。

这就是为什么没有显式调用String()方法,但输出结果却被改变的原因。这是Go语言接口系统的一个核心特性,允许类型自定义其在格式化输出中的表现。

回到顶部