[英]Why does my type's String() method not get called when printing a struct field?
I have a type called Password that is simply a string.我有一种称为 Password 的类型,它只是一个字符串。 I'd like to implement the Stringer interface by providing a String() method that redacts the value.
我想通过提供一个编辑值的 String() 方法来实现 Stringer 接口。
// Password a secret string that should not be leaked accidentally
type Password string
func (p Password) String() string {
return "*********" // redact the password
}
This works as I would expect, if I attempt to print a Password.如果我尝试打印密码,这将按我的预期工作。
p := Password("password not leaked here!")
fmt.Printf("password = %v \n", p)
// got... password = *********
But if the Password is a field within another struct, my String() method does not get called.但是如果密码是另一个结构中的一个字段,我的 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:*********}
Is there a way to make this call my String() method?有没有办法让这个调用我的 String() 方法? It appears that the code actually calls
refect.Value.String()
instead.看来代码实际上调用
refect.Value.String()
。
https://play.golang.org/p/voBrSiOy-ol 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!}
}
This is from the package fmt documentation:这是来自 package fmt 文档:
When printing a struct, fmt cannot and therefore does not invoke formatting methods such as Error or String on unexported fields.
打印结构时,fmt 不能也因此不会在未导出的字段上调用格式化方法,例如 Error 或 String。
The field password
is not exported, so it is not inspected to figure out it implements Stringer.字段
password
未导出,因此未检查它是否实现了 Stringer。 Export it, and it will work:导出它,它将起作用:
type User struct {
name string
Password Password
}
If you want a "failsafe" to protect yourself against accidental default formatting, you can hide your password values behind pointers by boxing a *string
in your Password type.如果您想要一个“故障安全”来保护自己免受意外的默认格式的影响,您可以通过在您的密码类型中装箱一个
*string
来隐藏您的密码值在指针后面。
https://play.golang.org/p/vE-cEXHp2ii 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)
}
Output: Output:
user = {name:Fran password:{string:0xc00008a040}}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.