我使用Gorp进行数据库访问,Gorp有一个标准 DbMap
类型,以及 Transaction
类型,当你想要能够回滚时 . 两种类型都实现 SqlExecutor
接口 .
因此,我正在针对 SqlExecutor
接口进行编程,因此如果需要我可以使用事务而无需更改我的代码 .
然后我初始化一个Gorp DbMap
或 Transaction
并将其作为字段属性传递 . 问题是我需要一个指向Gorp "object"的指针,否则如果我使用 Transaction
,如果Gorp "object"通过值而不是引用传递,我将如何能够回滚 .
然后我得到一条消息,如
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 回答
gorp.SqlExecutor
是一个接口,您永远不会使用指向接口值的指针 . 永远不能 .如果这是你的目标,那你就错了 . 接口是一个包装器,是一个保证行为的 Contract . 如果您的接口要求方法改变实现类型,那么实现类型应该是指针 . 指向接口本身的指针不会突然使实现类型变为可变 .
你的结构应该是
也许你是在思考这个问题,或者你可能仍然受到其他语言的“引用来电”影响:
gorp.SqlExecutor
是一个接口,您永远不会使用指向接口值的指针 . 永远不能 . (从技术上讲,这是不真实的,但如果你真的需要一个指向界面的指针,你就会掌握Go足以理解为什么"never ever"是一个非常好的建议 . )从不考虑"call by reference" . Go中没有这样的东西 . 将指针传递给函数不是"call by reference" . 把它留在后面 .
我假设你没有尝试使用事务并对非指针接口代码进行回滚?
背景:在Go中你传递一个指向某事物的指针,原因有两个:1)你想要因为你的结构非常大并且你想避免复制或2)你需要因为calee想要修改原文(这是典型的)对于带指针接收器的方法) . 现在接口值非常小(只有两个字),所以原因1将指针传递给接口值不适用 . 原因2在大多数情况下不适用,因为传递指向接口值的指针将允许您更改接口值本身,但通常您希望修改存储在接口值中的值 . 存储在接口值中的这个值通常是一个指针值,它允许通过调用包装指向此结构的指针的接口值来更改结构的值 . 这听起来很复杂,但是并没有使用指向接口的指针(因为这需要使用指向接口的指针(因为它不会做太多好处),除非他需要修改接口值,通常是在反射期间 .