william
william

Reputation: 479

How can I "cast" a pointer type in Go to match the type of the pointed-to value?

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.

Upvotes: 0

Views: 1954

Answers (1)

frank.lin
frank.lin

Reputation: 1694

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"

Upvotes: 2

Related Questions