Golang中Stringer接口的使用问题求助
Golang中Stringer接口的使用问题求助
//convert.go
package convert
type Liters float64
type Milliliters float64
func (l *Liters) ToMilliliters() Milliliters{
return Milliliters(*l * 1000)
}
func (m *Milliliters) ToLiters() Liters{
return Liters(*m / 1000)
}
func (m *Milliliters) String() string {
return fmt.Sprintf("%0.2f ml", *m)
}
func (l *Liters) String() string {
return fmt.Sprintf("%0.2f l", *l)
}
//main.go
package main
import (
"fmt"
"convert"
)
func main() {
vol := Liters(2)
fmt.Println(vol.ToMilliliters()) //输出 2000, 但我想要 2000.00 ml
}
注意:当方法使用值接收器时,我得到了正确的输出,即当我将 func (l *Liters) String() string 替换为 func (l Liters) String() string 时。
更多关于Golang中Stringer接口的使用问题求助的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你好!感谢回复。我确实没太理解这一点。
在我的例子中,Liters 和 Milliliters 是已定义类型。但是,我仍然可以在 vol(它是 Liters 类型)上调用具有指针接收者的 ToMilliliters() 方法,而无需使用指针,不是吗?
更多关于Golang中Stringer接口的使用问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你在这里提出了一个很好的观点。这段 Playground 代码 表明,String() 方法在 Milliliters 类型的变量上可以正常工作,但在 Milliliters 类型的返回值上却不行。
mvol := vol.ToMilliliters()
fmt.Println(mvol.String()) // 2000.00 ml
fmt.Println(vol.ToMilliliters().String()) // error: cannot call pointer method String on Milliliters
所以,我最初的分析过于草率了。
问题在于变量是可寻址的,而返回值不是。
. 操作符很智能,它既适用于值类型也适用于指针类型。对于指针,它会自动解引用。
但这对于不可寻址的返回值不起作用。
这就是一门语言包含便利特性时会发生的情况。这些特性可能有所帮助,但也可能引入像这样的意外行为。
另请参阅:go - “cannot take the address of” and “cannot call pointer method on” - Stack Overflow
编辑补充:
你的特定代码有一个非常直接的解决方案:使用值接收器。你的方法不会以任何方式修改接收器;因此,使用值接收器是完全没问题的。
你的问题是因为 String() 方法使用了指针接收器,而 fmt.Println 在调用 String() 方法时,需要能够获取到该方法的接收器。当你调用 vol.ToMilliliters() 时,返回的是 Milliliters 类型的值,而不是指针,因此无法调用指针接收器的 String() 方法。
以下是修改后的代码示例:
// convert.go
package convert
import "fmt"
type Liters float64
type Milliliters float64
func (l Liters) ToMilliliters() Milliliters {
return Milliliters(l * 1000)
}
func (m Milliliters) ToLiters() Liters {
return Liters(m / 1000)
}
func (m Milliliters) String() string {
return fmt.Sprintf("%0.2f ml", m)
}
func (l Liters) String() string {
return fmt.Sprintf("%0.2f l", l)
}
// main.go
package main
import (
"fmt"
"convert"
)
func main() {
vol := convert.Liters(2)
fmt.Println(vol.ToMilliliters()) // 现在输出 2000.00 ml
}
关键修改:
- 将所有方法改为值接收器(包括
String()方法) - 在
main.go中明确使用convert.前缀(假设包名正确)
这样修改后,fmt.Println 就能正确调用 Milliliters 类型的 String() 方法,输出格式化的字符串了。

