出于测试目的,我试图从database/sql
库中模拟Rows.Scan方法。签名如下:
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
方法设法对字符串进行了突变。
答案 0 :(得分: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
,它仍然不会更改。它仍然是相同的变量,仍位于相同的地址。我们在&s1
中传递了一个指针MockScan
,以便MockScan
可以使用该指针将一个值写入s1
。