php editor Xinyi introduces you how to use reflect.NewAt on interface{}. reflect.NewAt is a reflection library function in Go language, used to create a new instance on a given interface type. By using reflect.NewAt, we can dynamically create and initialize a new interface instance without specifying a specific type at compile time. This gives us greater flexibility and dynamics, allowing the code to be more versatile and extensible. The following will give you a detailed explanation of how to use reflect.NewAt to create an instance on interface{}.
package main import ( "encoding/json" "fmt" "reflect" "unsafe" ) type Stu struct { Name string `json:"name"` } func MakeStu() interface{} { return Stu{ Name: "Test", } } func main() { jsonData := []byte(`{"name":"New"}`) t1 := MakeStu() t2 := MakeStu() t3 := MakeStu() json.Unmarshal(jsonData, &t1) fmt.Println(t1) //Type of t1 becomes map[string]interface{} instead of struct Stu newPointer := reflect.New(reflect.ValueOf(t2).Type()).Interface() json.Unmarshal(jsonData, newPointer) fmt.Println(newPointer) //It works,but it need allocate memory to hold temp new variable brokenPointer := reflect.NewAt(reflect.ValueOf(t3).Type(), unsafe.Pointer(&t3)).Interface() json.Unmarshal(jsonData, brokenPointer) fmt.Println(brokenPointer) // I want to get the pointer of original type based on the existed variable t3,but it crashes. }
If I don't know the specific type of interface{} when coding, I can't use interface.(type) to cast. So how to use reflect.newat on interface{}?
If there is an interface that contains a method that returns interface{}, its specific type is struct, but I cannot determine the type of struct when coding. I need to use json.unmarshal to decode data encoded by json. I don't want to get map[string]interface{} , so I need to set the type of the receiver to a pointer to a concrete type of interface{} . Using reflect.new is simple, but consumes extra memory, so I'm curious how to use reflect.newat with an existing interface{}.
I would like to spend a few words explaining the problem.
Functions we have no control over makestu()
Returns an empty interface - not a concrete type. This will make the concrete type "invisible" to json.unmarshal()
and json.unmarshal()
treat it as an empty interface rather than a concrete type stu
. We have to communicate the concrete type to the unmarshaller somehow.
I would solve this problem using type switches:
func main() { jsondata := []byte(`{"name":"new"}`) t1 := makestu() switch c := t1.(type) { default: _ = json.unmarshal(jsondata, &c) t1 = c } fmt.println(t1) }
The type switch converts the empty interface to a concrete type, and json.unmarshal()
will treat it as a concrete type. You may still have extra allocations, but the code is more readable and you don't rely on reflection.
If I were feeling really adventurous, I would add a helper function that accepts a pointer to an empty interface, like this:
func unmarshal(data []byte, i *interface{}) (err error) { switch c := (*i).(type) { default: err = json.unmarshal(data, &c) *i = c } return err }
This will enable usage like this:
jsonData := []byte(`{"name":"New"}`) t1 := MakeStu() unmarshal(jsonData, &t1)
This looks clean to me and doesn't involve reflection, but it doesn't use reflect.newat()
as you yourself suggested. I hope you find my advice still useful.
The above is the detailed content of How to use reflect.NewAt on interface{}?. For more information, please follow other related articles on the PHP Chinese website!