为什么打印结构字段时不调用我的类型的 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!}
}

来自package fmt文档:

在打印结构体时,fmt不能也因此不会对未导出的字段调用Error或String等格式化方法。

字段password没有导出,因此不检查它是否实现了字符串。导出它,它将工作:

type User struct {
name     string
Password Password
}

如果你想要一个" failsafe ";为了保护你自己免受意外的默认格式,你可以通过在你的密码类型中包装一个*string来隐藏你的密码值。

https://play.golang.org/p/vE-cEXHp2ii

package main
import (
"fmt"
)
// Password a secret string that should not be leaked accidentally
type Password struct{
*string
}
func (p Password) String() string {
return "*********" // redact the password
}
func NewPassword(pword string) Password {
s := new(string)
*s = pword
return Password{s}
}
// User has a name and password
type User struct {
name     string
password Password
}
func main() {
user := User{"Fran", NewPassword("this password is safe from default formatting")}
fmt.Printf("user = %+v n", user)
}

输出:

user = {name:Fran password:{string:0xc00008a040}} 

相关内容

最新更新