0

出于测试目的,我试图从库中模拟Rows.Scan方法。database/sql签名如下所示:

func (r *Rows) Scan(dest ...interface{}) error

如何使用它的许多示例表明,您将指向字符串的指针(例如)传递给 Scan 方法,它将通过指针分配值。

var name string
rows.Scan(&name)

我一直在尝试重新创建类似的东西以供我自己理解并最终用于模拟,但它不起作用。

func MockScan(args ...interface{}) {
    var s2 string
    fmt.Println(args[0])
    args[0] = &s2
    fmt.Println(args[0])
}

func main() {
    var s1 string
    fmt.Println(&s1)
    MockScan(&s1)
    fmt.Println(&s1)
}

结果是:

0xc000012950
0xc000012950
0xc000012960
0xc000012950

我的初始字符串永远不会采用它的新值。我知道字符串是不可变的(尽管我对这个概念的真正理解有点摇摆不定)但是实际Rows.Scan方法设法改变了字符串。

4

1 回答 1

5

args[0] = &s2

这在MockScan. 您正在更改args[0]指向的内容,而不是更改指向的内容args[0]

你想做类似的事情

func MockScan(args ...interface{}) {
    // In real life, there would be some logic here to figure out what
    // kind of pointer we're dealing with, or some error handling to
    // handle the case where the user didn't pass a *string
    dst := args[0].(*string)
    *dst = "A new value"
}

func main() {
    var s1 string = "An old value"
    fmt.Println(s1)
    MockScan(&s1)
    fmt.Println(s1)
}

请注意,如果我们&s1在调用之前和之后在 main 中打印,它仍然不会更改。它仍然是同一个变量,它仍然在同一个地址。我们已经传递了一个指针&s1into MockScan,以便MockScan可以使用该指针将值写入s1

于 2019-10-09T15:23:34.187 回答