Golang调用接口指针的方法

时间:2014-01-22 12:17:25

标签: go

我正在使用Gorp进行数据库访问,Gorp有一个标准的DbMap类型,以及一个Transaction类型,以便您能够回滚。这两种类型都实现了SqlExecutor接口。

因此,我正在针对SqlExecutor接口进行编程,因此我可以根据需要使用事务而无需更改代码。

然后我初始化Gorp DbMapTransaction并将其作为字段属性传递。问题是我需要一个指向Gorp“对象”的指针,否则如果我使用Transaction,如果Gorp“对象”通过值而不是引用传递,我将如何能够回滚。

然后我收到一条消息,例如

r.Gorp.Get undefined (type *gorp.SqlExecutor has no field or method Get)

当我尝试使用我的代码时。我该如何调用这些方法?

代码示例如下。

package repositories

import (
    "github.com/coopernurse/gorp"
)


type Repository struct {
    Gorp *gorp.SqlExecutor // <<<< Need pointer so I can rollback
}

func (r *Repository) GetById(i interface{}, key interface{}) interface{} {
    obj, err := r.Gorp.Get(i, key)
    if err != nil {
        panic(err)
    }
    return obj
}

2 个答案:

答案 0 :(得分:16)

也许你是在思考这个问题,或者你可能仍然受到其他语言的“引用来电”影响:

  1. gorp.SqlExecutor是一个接口,您永远不会使用指向接口值的指针。永远不能。 (从技术上讲,这是不真实的,但如果你真的需要一个指向界面的指针,你就会掌握足以理解为什么“永远不会”是一个非常好的建议。)
  2. 永远不要考虑“参考电话”。 Go中没有这样的东西。将指针传递给函数不是“按引用调用”。把它留在后面。
  3. 我假设您没有尝试使用事务并对非指针接口代码进行回滚?

    背景:在Go中你传递一个指向某事物的指针,原因有二:1)你想要因为你的结构 并且你想避免复制或2)你需要因为calee想修改原文(这对于带有指针接收器的方法来说是典型的)。现在接口值非常小(只有两个字),所以原因1将指针传递给接口值不适用。原因2在大多数情况下不适用,因为传递指向接口值的指针将允许您更改接口 本身,但通常您希望修改该值存储里面的接口值。存储在接口值中的这个值通常是一个指针值,它允许通过调用包装指向此结构的指针的接口值来更改结构的值。这听起来很复杂但不是:新手Go程序员只是不使用指针接口(因为这不会有任何好处)和经验丰富的Go程序员不使用指针接口(因为它不会做太多好的)除非他需要修改界面值,通常是在反射过程中。

答案 1 :(得分:9)

  1. gorp.SqlExecutor是一个接口,您永远不会使用指针 到一个接口值。从来没有。

  2. 如果这是您的目标,那么您就错误地解决了这个问题。一个 interface是一个包装器,是一个保证行为的契约。如果 您的界面要求方法改变实现方式 类型,那么实现类型应该是一个指针。指向的指针 界面本身不会突然变成实现类型 可变的。

  3. 你的结构应该是

    type Repository struct {
        Gorp gorp.SqlExecutor 
    }
    
    
    func (r *Repository) GetById(i interface{}, key interface{}) interface{} {
        obj, err := r.Gorp.(gorp.SqlExecutor).Get(i, key)
        if err != nil {
            panic(err)
        }
        return obj
    }