英文:
How can I "cast" a pointer type in Go to match the type of the pointed-to value?
问题
我有一个包含不同变量类型的切片,包括字符串、整数等。有没有办法将*interface{}
指针根据需要转换为*string
或*int32
类型的指针。
这里有一个示例程序演示了这个问题:http://play.golang.org/p/J3zgrYyXPq
// 在切片中存储一个字符串
valSlice := make([]interface{}, 1)
var strVal string = "test"
valSlice[0] = strVal
// 创建指向该字符串的指针
ptrToStr := &valSlice[0]
// 输出 "string vs *interface {}"
fmt.Printf("%T vs %T\n", valSlice[0], ptrToStr)
// 尝试1(无法编译通过):
// ----------------------------
// 我该如何将指针类型转换为(*string),并引用与strVal相同的内存位置?
// 这段代码无法编译通过:
//var castPtr *string = &valSlice[0].(string)
// 尝试2(断言后,指针不指向相同的内存位置):
var sureType string = valSlice[0].(string)
var castPtr *string = &sureType
*castPtr = "UPDATED"
fmt.Println(valSlice[0]) // 输出 "test",而不是 "UPDATED"
如果我需要解释我想要这样做的原因,这里是解释。database/sql
包在扫描值时会查看指针类型。我的代码已经准备了一个切片,其中包含了正确类型的零值变量,以匹配结果集。
因为Scan
需要指针,所以我遍历我的切片,并构建一个指向原始切片中变量的指针切片。然后将这个指针切片传递给Scan
函数。但是,由于上述创建指针的操作会导致一个*interface{}
指针,而不是与变量类型匹配的指针,所以Scan
函数无法知道底层数据类型,无法将原始的[]byte
值转换为正确的类型。
英文:
I have a slice that contains different variable types. Some strings, integers, etc. Is there any way for me to "cast" a pointer to one of these values from *interface{}
to *string
or *int32
where appropriate.
Here is a toy program that demonstrates the issue: http://play.golang.org/p/J3zgrYyXPq
// Store a string in the slice
valSlice := make([]interface{}, 1)
var strVal string = "test"
valSlice[0] = strVal
// Create a pointer to that string
ptrToStr := &valSlice[0]
// Outputs "string vs *interface {}"
fmt.Printf("%T vs %T\n", valSlice[0], ptrToStr)
// Attempt 1 (doesn't compile):
// ----------------------------
// How can I cast the pointer type to (*string), referencing the same
// memory location as strVal?
// This doesn't compile:
//var castPtr *string = &valSlice[0].(string)
// Attempt 2 (after assertion, doesn't point to the same memory location):
var sureType string = valSlice[0].(string)
var castPtr *string = &sureType
*castPtr = "UPDATED"
fmt.Println(valSlice[0]) // Outputs "test", not "UPDATED"
If I need to justify my desire to do this, here's the explanation. The database/sql
package looks at the pointer type when scanning values. My code has already prepared a slice holding zero-valued variables of the correct types to match the resultset.
Because Scan
requires pointers, I iterate over my slice and build a new slice of pointers to the variables in my original slice. I then pass this slice of pointers into the Scan
. But because the act of creating a pointer as above results in an *interface{}
pointer instead of one that matches the variable type, the Scan
does not know the underlying datatype to convert the raw []byte
value to.
答案1
得分: 2
你必须知道,当一个变量被赋值给一个接口时,会发生什么?
str := "hello world"
var tmp interface{} = str
编译器会创建一个临时对象,该对象的值与 str
相同,并将 tmp
与之关联。因此,在此之后,对 tmp
所做的任何操作都与 str
无关。但是 Go 不允许你更改临时对象。所以你不能在接口中解引用临时对象,也不能更改它,这就是错误存在的原因。如果你想了解更多关于接口实现的信息,请阅读 http://research.swtch.com/interfaces
如果你想改变原始对象,可以将指针传递给接口:
valSlice := make([]interface{}, 1)
var strVal string = "test"
valSlice[0] = &strVal // 将指针传递给接口
var castPtr *string = valSlice[0].(*string) // 获取指针
*castPtr = "UPDATED" // 改变字符串 strVal
fmt.Println(strVal) // 输出 "UPDATED"
英文:
1 You must know , when a var is assigned to a interface , what happend ?
str := "hello world"
var tmp interface{} = str
the complier will create a tempotary object , which has the same value with str
,and tmp
is associated with it. So after that , all you do to tmp
is not associated with str
. But go doesn't allow you to change the tempotary object。 So you can't have the dereference of the tempotary object in interface
and you can't change it, that's why the errors exist. If you want more information about the implements of interface
, read http://research.swtch.com/interfaces
2 If you want change the original object, pass the pointer to a interface
valSlice := make([]interface{}, 1)
var strVal string = "test"
valSlice[0] = &strVal //pass a pointer to a interafce
var castPtr *string = valSlice[0].(*string) // get the pointer
*castPtr = "UPDATED"//change the string strVal
fmt.Println(strVal) // Outputs "UPDATE"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论