Need to construct interface/pointer using Reflect in Golang, not working - go

So, this works:
house := model.House {};
err = db.First(&house).Error;
However, this doesn't work:
var house model.House;
fetchFromDatabase := reflect.New(reflect.TypeOf(house)).Interface();
err = db.First(&fetchFromDatabase).Error;
... The database library gives the error:
unsupported destination, should be slice or struct
To me, that should be a struct, considering the "House" type is a struct. However, I'm still wrapping my head around Reflect ... can anyone help?

The library is complaining because the application is passing a *interface{} to the method. The value fetchFromDatabase is a pointer to a struct. Pass this value directly to the method:
var house model.House
fetchFromDatabase := reflect.New(reflect.TypeOf(house)).Interface()
err = db.First(fetchFromDatabase).Error

Related

Obtaining an addressable copy of a reflect.Value

I want to add marshalling/unmarshalling to types that I accept, in a way similar JSON custom encoding/decoding. I have it all working great when the type implements a Marshal method (value receiver) and Unmarshal method (pointer receiver).
The Unmarshal method must obviously use a pointer receiver so that the new value is saved. I have been told that a Marshal method using a pointer (not value) receiver should also be allowed. The trouble with this is I am using a reflect.Value which is not always addressable.
Here's an edited extract of the code which panics:
var v reflect.Value // passed in parameter
t := v.Type()
pt := reflect.TypeOf(reflect.New(t).Interface())
if t.Implements(reflect.TypeOf((*Marshaler)(nil)).Elem()) {
str, err = v.Interface().(Marshaler).MarshalXXX()
// ... value receiver WORKS FINE
} else if pt.Implements(reflect.TypeOf((*Marshaler)(nil)).Elem()) {
str, err = v.Addr().Interface().(Marshaler).MarshalXXX()
// ptr receiver gives PANIC value is not addressable
I tried creating a copy of v, but the copy is also not addressable which makes no sense to me:
tmp := reflect.New(v.Type())
tmp.Addr().Set(v)
str, err = tmp.Interface().(Marshaler).MarshalXXX()
In case I have not explained this well here is an example on the Go Playground for you to try:
Also while I am here: Is there a better way to get the type of a pointer to a the type than in the assignment to pt above?
I found the answer. The problem was I was using Addr instead of Elem. Though that begs the question why Set worked, since the panic did not occur till the following line.
In summary, to create an addressable copy of a reflect.Value v do this:
tmp := reflect.New(v.Type()) // create zero value of same type as v
tmp.Elem().Set(v)
Please forgive me asking prematurely, but I had already spent 4 hours trying to solve the problem. For completeness here is the fix to my Go playground code in the question.

Dynamically create protocol buffer object

I'm working with a set of protocol buffers and I'm having trouble wrapping my head around what I need to do to instantiate them and it has to be calculated at runtime. I know I somehow need to use reflect to do this, but nothing seems to work. At compile time, I only know the first protocol buffer that I need to create. That buffer contains a field that tells me an integer id of the next one I need to create.
All of my buffers are defined in a package called kpb.
I find that first one like this:
info := &kpb.ArchiveInfo{}
err := proto.Unmarshal(<byte array>, info)
// error handling
messageType = *info.MessageType // 1
I have a map that defines the next buffers I need to call. That map is defined like this:
Note that all of the values of this map are proto.ProtoMessage objects, but using that seemed to cause more problems than it solved.
var registryMap = map[uint32]interface{}{
1: &kpb.KNDocumentArchive{},
...etc
}
So when I reference this map, I'm doing it like this:
var klass interface{}
//stuff
klass = registryMap[messageType]
fmt.Println(klass) // *kpb.KNDocumentArchive
But, what I can't figure out is how to instantiate a variable with the proper type to Unmarshal the payload I have.
I can get the type of the klass by doing this:
klassType := reflect.TypeOf(klass)
fmt.Println(klassType) // kpb.KNDocumentArchive - as expected
But, if I try to create a new variable with it, I get an error
payloadObj := new(klass)
// klassType (variable of type reflect.Type) is not a type
So even though the type is kpb.KNDocumentArchive like I expect, it's still somehow reflect.Type
When I used proto.ProtoMessage as the type for the map return, I could get past this part and have the variable instantiated, but I couldn't pass that to proto.Unmarshal because it, rightly, expects the type to be kpb.KNDocumentArchive
What am I doing wrong here?
I was able to figure this out. I needed to use proto built in features. The end result was updating my map to this:
var registryMap = map[uint32]string{
1: "KN.KNDocumentArchive",
}
And then the unmarshaling part was solved with this:
func GetProto(id uint32, messageBytes []byte) proto.Message {
klass := registryMap[id]
if klass == "" {
panic("Don't know how to parse Protobuf message type " + fmt.Sprint(id))
}
messageName := protoreflect.FullName(klass)
pbtype, err := protoregistry.GlobalTypes.FindMessageByName(messageName)
if err != nil {
panic(err)
}
msg := pbtype.New().Interface()
err = proto.Unmarshal(messageBytes, msg)
if err != nil {
panic(err)
}
return msg
}

working with slices of pointers to structs with reflection

I'm trying to practice reflections with Go, I read a few articles but it seems like I'm missing some basic understanding that maybe you guys can clear out.
I wrote a simple app to demonstrate what I'm trying to achieve.
in general I want a function to receive a slice of a pointer to a struct as an interface type, and to fill it with data using reflections.
again. this example seems a bit useless but i minimized what i'm trying to achieve. I know how to find the column names of a struct, but i have no problem there so I removed it from the example.
so this is the code:
package main
import (
"log"
"reflect"
"unsafe"
)
type MyTesting struct {
MyBool bool
MyFloat float64
MyString string
}
func addRow(dst interface{}) {
iValue := reflect.ValueOf(dst)
iType := reflect.TypeOf(dst)
// getting the Struct Type (MyTesting)
structType := iType.Elem().Elem().Elem()
// creating an instance of MyTesting
newStruct := reflect.New(structType)
// getting the current empty slice
slice := iValue.Elem()
// appending the new struct into it
newSlice := reflect.Append(slice,newStruct)
// trying to set the address of the varible to the new struct ? the original var is not a pointer so something here
// is clearly wrong. I get the PANIC here, but if i remove that line, then rows stays nil
reflect.ValueOf(&dst).SetPointer(unsafe.Pointer(newSlice.Pointer()))
currentPlaceForRow := newStruct.Elem()
structField := currentPlaceForRow.FieldByName("MyString")
structField.SetString("testing")
}
func main() {
var rows []*MyTesting
addRow(&rows)
log.Print(rows)
}
so in general i the function gets an un-initialized slice of pointers to MyTesting struct. i want in the function to create the first slice element and to set the value of MyString in the 1st element to "testing".
when I try to execute it I get:
panic: reflect: reflect.Value.SetPointer using unaddressable value
so working with reflections is a bit confusing for me.. can anyone please a shed a light on what I'm missing here ? :)
You can use reflect.ValueOf(dst).Elem().Set(newSlice).
https://play.golang.org/p/ilDZxHc2H-x

Using empty interfaces in go

I am trying to understand the code that is used at my company. I am new to go lang, and I have already gone through the tutorial on their official website. However, I am having a hard time wrapping my head around empty interfaces, i.e. interface{}. From various sources online, I figured out that the empty interface can hold any type. But, I am having a hard time figuring out the codebase, especially some of the functions. I will not be posting the entire thing here, but just the minimal functions in which it has been used. Please bear with me!
Function (I am trying to understand):
func (this *RequestHandler) CreateAppHandler(rw http.ResponseWriter, r *http.Request) *foo.ResponseError {
var data *views.Data = &views.Data{Attributes: &domain.Application{}}
var request *views.Request = &views.Request{Data: data}
if err := json.NewDecoder(r.Body).Decode(request); err != nil {
logrus.Error(err)
return foo.NewResponsePropogateError(foo.STATUS_400, err)
}
requestApp := request.Data.Attributes.(*domain.Application)
requestApp.CreatedBy = user
Setting some context, RequestHandler is a struct defined in the same package as this code. domain and views are seperate packages. Application is a struct in the package domain. The following two structs are part of the package views:
type Data struct {
Id string `json:"id"`
Type string `json:"type"`
Attributes interface{} `json:"attributes"`
}
type Request struct {
Data *Data `json:"data"`
}
The following are part of the package json:
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
func (dec *Decoder) Decode(v interface{}) error {
if dec.err != nil {
return dec.err
}
if err := dec.tokenPrepareForDecode(); err != nil {
return err
}
if !dec.tokenValueAllowed() {
return &SyntaxError{msg: "not at beginning of value"}
}
// Read whole value into buffer.
n, err := dec.readValue()
if err != nil {
return err
}
dec.d.init(dec.buf[dec.scanp : dec.scanp+n])
dec.scanp += n
// Don't save err from unmarshal into dec.err:
// the connection is still usable since we read a complete JSON
// object from it before the error happened.
err = dec.d.unmarshal(v)
// fixup token streaming state
dec.tokenValueEnd()
return err
}
type Decoder struct {
r io.Reader
buf []byte
d decodeState
scanp int // start of unread data in buf
scan scanner
err error
tokenState int
tokenStack []int
}
Now, I understood that, in the struct Data in package views, Application is being set as a type for the empty interface. After that, a pointer to Request in the same package is created which points to the variable data.
I have the following doubts:
What exactly does this keyword mean in Go? What is the purpose of writing this * RequestHandler?
Initialization of a structure in Go can be done while assigning it to a variable by specifying the values of all it's members. However, here, for the struct Data, only the empty interface value is assigned and the values for the other two fields are not assigned?
What is the advantage of assigning the Application struct to an empty interface? Does it mean I can use the struct members using the interface variable directly?
Can someone help me figure out the meaning of this statement? json.NewDecoder(r.Body).Decode(request)?
While I know this is too much, but I am having a hard time figuring out the meaning of interfaces in Go. Please help!
this is not a keyword in go; any variable name can be used there. That is called the receiver. A function declared in that way must be called like thing.func(params), where "thing" is an expression of the type of the receiver. Within the function, the receiver is set to the value of thing.
A struct literal does not have to contain values for all the fields (or any of them). Any fields not explicitly set will have the zero value for their types.
As you said, an empty interface can take on a value of any type. To use a value of type interface{}, you would use type assertion or a type switch to determine the type of the value, or you could use reflection to use the value without having to have code for the specific type.
What specifically about that statement do you not understand? json is the name of a package in which the function NewDecoder is declared. That function is called, and then the Decode function (which is implemented by the type of the return value of NewDecoder) is called on that return value.
You may want to take a look at Effective Go and/or The Go Programming Language Specification for more information.

Golang: How to change struct field value in slice of interfaces

Problem in Playground: https://play.golang.org/p/UKB8f4qGsM
I have a slice of interfaces, I know for sure which type they have (in reality i don't so I'd have to type switch it, but I left that out for clarity). How can I assign a value to a field in the struct behind the interface? The type assertion seems to take away the reference.
I also tried using pointers, that too doesn't work though, mostly because I can't type assert then (type *inter cannot be type asserted) and when I dereference it, it kinda makes it pointless to even have...
I'm not that experienced in Go, I would appreciate every help I can get.
You can't change the value stored in the interface, you need to use a pointer to the value you want to change:
for i := 0; i < 5; i++ {
slice = append(slice, &b{a: a{name: "Tom"}})
}
for i, _ := range slice {
x := slice[i].(*b)
x.name = "Tim"
}

Resources