为什么在打印结构字段时我的类型的String()方法没有被调用?
我有一个叫做 Password 的类型,它只是一个字符串。我想通过提供一个编辑值的 String() 方法来实现 Stringer 接口。
// Password a secret string that should not be leaked accidentally
type Password string
func (p Password) String() string {
return "*********" // redact the password
}
如果我尝试打印密码,这将按我的预期工作。
p := Password("password not leaked here!")
fmt.Printf("password = %v n", p)
// got... password = *********
但是,如果 Password 是另一个结构中的字段,则不会调用我的 String() 方法。
// User has a name and password
type User struct {
name string
password Password
}
user := User{"Fran", Password("password was leaked!")}
fmt.Printf("user = %+v n", user)
// got... user = {name:Fran password:password was leaked!}
// expected... user = {name:Fran password:*********}
有没有办法让这个调用我的 String() 方法?看来代码实际上是在调用refect.Value.String()。
https://play.golang.org/p/voBrSiOy-ol
package main
import (
"fmt"
)
// Password a secret string that should not be leaked accidentally
type Password string
func (p Password) String() string {
return "*********" // redact the password
}
// User has a name and password
type User struct {
name string
password Password
}
func main() {
s := Password("password not leaked here!")
fmt.Printf("password = %v n", s) // password = *********
user := User{"Fran", Password("password was leaked!")}
fmt.Printf("user = %+v n", user) // user = {name:Fran password:password was leaked!}
}
回答
这是来自包 fmt 文档:
打印结构时, fmt 不能,因此不会在未导出的字段上调用诸如 Error 或 String 之类的格式化方法。
该字段password未导出,因此不会对其进行检查以确定它实现了 Stringer。导出它,它将起作用:
type User struct {
name string
Password Password
}