如何取消引用作为空接口传递的指针值?

时间:2018-03-28 17:05:38

标签: pointers go interface

我有一个方法在我用于数据库访问的类型上使用target interface{},如:

func (c *client) Query(query someType, target interface{}) error {
    return c.db.Query(query).Decode(target)
}

然后将其称为

result := resultType{}
if err := c.Query(myQuery, &result); err == nil {
    // do sth with result
}

当我传递result

的指针地址时,我想要它做什么

我现在遇到的麻烦是我不知道如何在测试中模仿这种行为(改变传递的引用)。

如果我不需要通过interface{},我可以想象它是这样做的:

type mockClient struct {
    targetValue resultType
}

func (m *mockClient) Query(query someType, target *resultType) error {
    *target = m.targetValue
    return nil
}

如果我尝试使用我的实际签名做同样的事情,我无法取消引用target中包含的值,如下所示:

type mockClient struct {
    targetValue interface{}
}

func (m *mockClient) Query(query someType, target interface{}) error {
    target = m.targetValue // this does not mutate the passed target
    return nil
} 

当它作为空接口传入时,是否可以取消引用指针值?如果不可能,那么测试副方法的另一种方法是什么,而不必使用具体类型作为参数?

1 个答案:

答案 0 :(得分:1)

您可以使用'reflect'包来执行此操作。

package main

import (
    "fmt"
    "reflect"
)

type mockClient struct {}

func (m *mockClient) Query(query string, target interface{}) error {
    a := "changed"
    va := reflect.ValueOf(a)
    reflect.ValueOf(target).Elem().Set(va)
    return nil
}

func main() {
    var mc mockClient
    target := "initial"
    mc.Query("qwe", &target)
    fmt.Println(target)
}

引用您的简单示例可以找到here