簡體   English   中英

為什么在打印結構字段時不調用我的類型的 String() 方法?

[英]Why does my type's String() method not get called when printing a struct field?

我有一種稱為 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 = ********* 

但是如果密碼是另一個結構中的一個字段,我的 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未導出,因此未檢查它是否實現了 Stringer。 導出它,它將起作用:

type User struct {
    name     string
    Password Password
}

如果您想要一個“故障安全”來保護自己免受意外的默認格式的影響,您可以通過在您的密碼類型中裝箱一個*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)
}

Output:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM