登录
首页 >  Golang >  Go问答

为何在输出结构体字段时没有调用到我的自定义 String() 方法?

来源:stackoverflow

时间:2024-03-03 22:54:26 116浏览 收藏

来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习Golang相关编程知识。下面本篇文章就来带大家聊聊《为何在输出结构体字段时没有调用到我的自定义 String() 方法?》,介绍一下,希望对大家的知识积累有所帮助,助力实战开发!

问题内容

我有一个名为“密码”的类型,它只是一个字符串。我想通过提供一个编辑值的 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!}
}

解决方案


这来自 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)
}

输出:

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

到这里,我们也就讲完了《为何在输出结构体字段时没有调用到我的自定义 String() 方法?》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>