Golang类型断言

21

我已经创建了一个基于字符串的类型Role,现在我正在尝试通过实现Valuer和Scanner接口来使它与数据库驱动程序一起工作。

type Role string

func (r *Role) Scan(value interface{}) error {
    r = (*Role)(value.(string))

    return nil
}

func (r *Role) Value(value driver.Value, err error) {
    if err != nil {
        value = string(r)
    }
}

我一直收到这个错误:

The Go code app/entities/user.go does not compile: cannot convert value.(string) (type string) to type *Role

我在这里做错了什么?

2个回答

24

以下是第一个函数的可运行代码:

func (r *Role) Scan(value interface{}) error {
    *r = Role(value.(string))
    return nil
}

尽管您可能希望使用 s, ok := value.(string) 并为 !ok 返回错误而不是 panic。

driver.Valuer 的签名不是您提供的,而是:

func (r Role) Value() (driver.Value, error) {
    return string(r), nil
}

请注意,此代码不处理或产生 NULL 值。

Playground


2
啊哈,是指针解引用卡住了我。 - Lee
2
第二个问题的解决方案是:func (r *Role) Value(value driver.Value, err error) { if err != nil { value = string(*r) } } - Lee
1
很有趣。我从未见过修改方法接收器的Go代码,也不会考虑这样做。我还确信从接口转换为具体类型需要类型断言。 - Günter Zöchbauer
2
有一种类型断言,value.(string) - Lee
1
我明白了,只是忽略了第二个返回值。 - Günter Zöchbauer
显示剩余2条评论

4

我认为在Scan方法中修改方法的接收器(r)并不是一个好主意。

你需要进行类型断言将value interface{}转换为字符串。
你试图将string转换为Role指针

func (r *Role) Scan(value interface{}) (retVal Role, err error) {
    var s string;

    if v,ok := value.(string); ok {
      s = v;
    }
    var rx Role
    rx = Role(s)

    var rx2 *Role
    rx2 = &rx
    _ = rx // just to silence the compiler for this demonstration
    _ = rx2 // just to silence the compiler for this demonstration
    return rx, nil
}

应该可以工作


如果我们不修改接收器或返回一个值,那么驱动程序如何知道要做什么? - Lee
接收器r类似于对象中的“this”。在Go语言中,您可以返回多个值(值和错误)。我不知道您对Scan方法有什么要求。 - Günter Zöchbauer
是的,但扫描的工作是将从数据库发送回来的字符串转换为一个角色,这被分配给rx,但不是分配给r也没有被返回,只有局部变量获得了结果。我错过了什么。 - Lee
1
Scanner 接口将 scan 定义为 Scan(src interface{}) error,您正在返回多个结果。 - Lee
那么你只能返回错误,不能返回其他任何东西。你能提供Scanner接口的API文档链接吗?这样我就可以查看它是关于什么的了。 - Günter Zöchbauer
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接