We are using the openapi-generator to generate a go-gin-server. This generates models containing properties of type *interface{} eg.
type Material struct {
Id *interface{} `json:"id,omitempty"`
Reference *interface{} `json:"reference,omitempty"`
}
If I have an instance of this struct, with nil pointers, how can these be set? I have tried the following:
theReturnId := "abc123"
material.Id = &theReturnId
This gives a compilation error of:
cannot use &theReturnId (value of type *string) as *interface{} value in assignment: *string does not implement *interface{} (type interface{} is pointer to interface, not interface)
theReturnId := "abc123"
*material.Id = theReturnId
This gives a runtime error that the pointer is nil.
I have tried a bunch of other things but to no avail. What am I missing here? Thanks!
You almost never need a pointer to an interface. You should be passing interfaces as values, but the underlying data though can still be a pointer.
You need to reconsider your design/code generation technique to not use such an approach as it is not idiomatic Go.
If you still want to use it, use a typed interface{} variable and take its address. The way you are doing in your example is incorrect as theReturnId is a string type taking its address would mean *string type, which cannot be assigned to *interface{} type directly as Go is a strongly typed language
package main
import "fmt"
type Material struct {
Id *interface{} `json:"id,omitempty"`
Reference *interface{} `json:"reference,omitempty"`
}
func main() {
newMaterial := Material{}
var foobar interface{} = "foobar"
newMaterial.Id = &foobar
fmt.Printf("%T\n", newMaterial.Id)
}
theReturnId := "abc123"
*material.Id = theReturnId
This gives a runtime error that the pointer is nil.
Because the field Id is set to its zero value, i.e.: nil, and dereferencing it (*material.Id) results in a run-time error. You can write a constructor for Material that initializes its *interface{} fields:
func NewMaterial() Material {
return Material {
new(interface{}),
new(interface{}),
}
}
Now, you can safely dereference the field Id:
material := NewMaterial()
theReturnId := "abc123"
*material.Id = theReturnId
Related
I am confused whether to use a & with go when declaring a variable and init with a struct
say we have a struct wrapper
type HttpResult struct {
Status int32 `json:"status"`
Msg string `json:"msg"`
Data interface{} `json:"data,omitempty"`
}
and a struct defining the user model
type OmUser struct {
Id primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Name string `json:"name"`
Password string `json:"password"`
Email string `json:"email"`
}
And the following declaring seems give the same result:
myOmUser := OmUser{ //note no & sign here
Name: "Tony",
Password: "mypass",
Email: "tony#foo.com"
}
httpResult := &HttpResult{
Status: 0,
Msg: "ok",
Data: myOmUser,
}
js, _ := json.Marshal(httpResult)
fmt.Println(js)
Or
myOmUser := &OmUser{ //note the & sign
Name: "Tony",
Password: "mypass",
Email: "tony#foo.com"
}
httpResult := &HttpResult{
Status: 0,
Msg: "ok",
Data: myOmUser,
}
js, _ := json.Marshal(httpResult)
fmt.Println(js)
so, when to use & and why?
In your particular example it doesn't make a difference.
But when we look at an example of using json.Unmarshal() it makes a bit more sense:
jsonBlob := []byte(`{"id": "1", "name": "bob", "password": "pass", "email", "hi#me.com"}`)
var newOmUser OmUser
err := json.Unmarshal(jsonBlob, &newOmUser)
if err != nil {
panic(err)
}
Here we declare the variable before hand, and then we use the & to pass a pointer to that variable into the Unmarshal function.
That means that the Unmarshal function can reach out and update that variable, even though it's declared outside of the function.
Without the &, the Unmarshal function would get a copy of the newOmUser variable, and it would leave the original newOmUser variable that we declared empty.
When it comes to pointers, my general rule of thumb is:
Don't use them unless you have to.
If you need to use any unmarshalling functions, you'll need them. There are lots of other functions that make use of them.
Here's a quick exercise that helps me understand a little more about pointers:
func uppercase(s string) {
s = strings.ToUpper(s)
fmt.Println(s)
}
// Same as the uppercase() function, but works with a pointer.
func uppercasePointer(s *string) {
*s = strings.ToUpper(*s)
fmt.Println(*s)
}
name := "bob"
uppercase(name) // prints 'BOB'
fmt.Println(name) // prints 'bob' - our variable was not changed
name2 := "bobpointer"
uppercasePointer(&name2) // prints 'BOBPOINTER'
fmt.Println(name2) // prints 'BOBPOINTER' - our variable was changed
When we call the uppercase(name) function, go makes a copy of the name variable and sends it to the uppercase function.
Whatever the function does to that copy that it received stays in the function. The original variable that we declared outside the function is not changed.
When we call the uppercasePointer(&name2) function, we are sending a pointer to the name2 variable we declared.
The function can use that pointer to reach out and update the name2 variable that we declared earlier.
At first, you might not see the point of pointers, but as you continue to use go, you will see that they help us solve some complex problems.
Empty interface type in Go can hold values of any type. Tour here.
So in your HttpResult.Data is an empty interface type. So you can assigne any type to it.
The difference between defining a variable with & is getting a pointer of that type. Tour here.
Those are obviously two types with two different functionalities in Go. But you can assign both to empty interface type variable because its accepting values of any type.
package main
import (
"fmt"
"reflect"
)
type OmUser struct {
}
func main() {
myOmUser := OmUser{}
myOmUser2 := &OmUser{}
fmt.Println(reflect.TypeOf(myOmUser)) //main.OmUser
fmt.Println(reflect.TypeOf(myOmUser2)) //*main.OmUser
}
For more details about &, read Go doc address operators
For an
operand x of type T, the address operation &x generates a pointer of
type *T to x. The operand must be addressable, that is, either a
variable, pointer indirection, or slice indexing operation; or a field
selector of an addressable struct operand; or an array indexing
operation of an addressable array. As an exception to the
addressability requirement, x may also be a (possibly parenthesized)
composite literal. If the evaluation of x would cause a run-time
panic, then the evaluation of &x does too.
fooA := &Foo{}
fooA has type *Foo.
fooB := Foo{}
fooB has type Foo.
https://tour.golang.org/moretypes/1
In practice, this means if you had a func that accepted type *Foo you could do either of the following...
func someFunc(f *Foo) {
// ...
}
fooA := &Foo{}
someFunc(fooA)
fooB := Foo{}
someFunc(&fooB)
So realistically, create whichever you need to be honest.
I'm trying to set struct.field = &otherStruct. However, I have to use reflection, and otherStruct is of type interface{}.
The error I'm getting is:
reflect.Set: value of type main.StructB is not assignable to type *main.StructB
struct is known. The (real) type of otherStruct is not known, but it is guaranteed, that the assignment is safe (the struct type is identical).
Code:
type StrucA struct {
Field *StrucB
}
type StrucB struct {}
func main() {
a := StrucA{}
var b interface{} = StrucB{}
//above is set
// Target: Set a.Field = &b
reflect.ValueOf(&a).Elem().FieldByName("Field").Set(reflect.ValueOf(b)) // reflect.Set: value of type main.StrucB is not assignable to type *main.StrucB
}
Playground:
https://play.golang.org/p/LR_RgfBzsxa
I have tested a lot of different stuff, but I'm unable to solve it.
You first need to allocate a pointer to the type of b, in order to have somewhere to copy the value. Once you have a pointer value, you can set that to Field in a:
field := reflect.New(reflect.TypeOf(b))
field.Elem().Set(reflect.ValueOf(b))
reflect.ValueOf(&a).Elem().FieldByName("Field").Set(field)
https://play.golang.org/p/6-GNSEq0tw3
Simple golang app gives below error
.\test.go:13: cannot use ds (type Data_A) as type []interface {} in field value
for below code
package main
type Data_A struct {
a string
}
type DTResponse struct {
Data []interface{} `json:"data"`
}
func main() {
ds := Data_A{"1"}
dtResp := &DTResponse{ Data:ds}
print(dtResp)
}
I would like to have a struct with slice variable of any type. Using struct{} gives the same error.
In Java I could use Object as it is the parent object of any object. But I could not find such one in golang.
Any help would be appreciated.
Yes, as a slice of interface{} which can hold any arbitrary value.
var s = []interface{}{1, 2, "three", SomeFunction}
fmt.Printf("Hello, %#v \n", s)
Output:
Hello, []interface {}{1, 2, "three", (func())(0xd4b60)}
https://play.golang.org/p/MQMc689StO
But I do not recommend simulate dynamic-typed languages (like Python, JavaScript, PHP, etc) this way. Better to use all static-typed benefits from Go, and leave this feature as a last resort, or as a container for user input. Just to receive it and convert to strict types.
Typing
Go is a strongly explicitly typed language thus you can't substitute an object of one type with another (it is already compiled in this way). Also when you do type Data_A struct {... you define new type named Data_A. []interface{} and Data_A are completely different types and these types (like any other) are not interchangeable. Note, even interface{} is not interchangeable with anything. You can pass any type in a function like this func f(a interface{}){... but inside the function you will have exactly interface{} type and you should assert it to use properly.
Fix#1
package main
type Data_A struct {
a string
}
type DTResponse struct {
Data Data_A `json:"data"`
}
func main() {
ds := Data_A{"1"}
dtResp := &DTResponse{ Data:ds}
print(dtResp)
}
Fix#2
package main
type DTResponse struct {
Data []interface{} `json:"data"`
}
func main() {
ds := []interface{}{"1"}
dtResp := &DTResponse{ Data:ds}
print(dtResp)
}
Possibly the cause of confusion: struct is not slice or array.
I tried :
var a [100]int
func fun1(src interface{}) interface{} {
src, _ = src.([100]int) // changed []int to [100]int
fmt.Println(reflect.TypeOf(src)) // result: []int
dest := make([]int, len(src))
return dest
}
there is an error:
message: 'invalid argument src (type interface {}) for len'
But if I redefine a variable:
var a [100]int
func fun1(src interface{}) interface{} {
slice_src, _ := src.([100]int) //changed []int to [100]int
fmt.Println(reflect.TypeOf(slice_src)) // result: []int
dest := make([]int, len(slice_src))
return dest
}
it will be ok.
why reflect.TypeOf(src) will print []int after I used src.([]int) but error shows src is still interface{} ?
I have checked this convert interface{} to int, but I still don't understand how to use correct conversion.
There is another question:
I changed the []int to [100]int since the type assertion before will return [] and false.
But if I don't know the type of a, how can I use type assertion to transfer an array (like[99]int) as a interface{} to function and return slice ([]int)?
when you first declare src, in fun1(src interface{}) you are making a variable of type interface. Which, of course cannot have len called on it.
The reason reflect.TypeOf says []int is due to how TypeOf works.
It takes an interface{} and tells you the type of the thing in the interface{}
so, in the first example, you already had an interface
and in the second example, go automatically created an interface{} instance to hold your []int slice.
Quoting dynamic type from Variables :
The static type (or just type) of a variable is the type given in its declaration, the type provided in the new call or composite literal, or the type of an element of a structured variable. Variables of interface type also have a distinct dynamic type, which is the concrete type of the value assigned to the variable at run time (unless the value is the predeclared identifier nil, which has no type). The dynamic type may vary during execution but values stored in interface variables are always assignable to the static type of the variable.
In the first example, src has a dynamic type. Value of the src will be of type []int during execution but eventually, type will be interface since it is dynamic type & it was of type interface at the time of declaration. Hence, you need to change variable src to the new variable during type assertion.
Similar to what you did in second example: slice_src, _ := src.([]int)
You can not even do src, _ := src.([]int) as you will end up with error no new variables on left side of :=
There is a type switch method using reflect.TypeOf() : golang type assertion using reflect.Typeof()
and
How to get the reflect.Type of an interface?
Quote How to get the reflect.Type of an interface? :
You can't. Type assertions allow you to take advantage of the static type checking that the language gives you even if you have an interface, whose type isn't statically checked. It basically works something like this:
You have some statically typed variable s, which has type t. The compiler enforces the guarantee that s always has type t by refusing to compile if you ever try to use s as if it were a different type, since that would break the guarantee.
I'm running into a slight architectural problem with Golang right now that's causing me to copy/paste a bit more code than I'd prefer. I feel like there must be a solution, so please let me know if this is perhaps possible:
When I pass things through an interface {}-typed function parameter, I start getting errors such as "expected struct or slice", etc. ... even though what I passed was previously a struct or a slice. I realize that I could manually convert these to another type after receiving them in that function, but then that become tedious in instances such as this:
local interface type *interface {} can only be decoded from remote
interface type; received concrete type
... In this case, the receiving function seems like it'd need to be hard-coded to convert all interface {} items back to their respective original types in order to work properly, because the receiving function needs to know the exact type in order to process the item correctly.
Is there a way to dynamically re-type Golang interface {} typed variables back to their original type? Something like this, How to I convert reflect.New's return value back to the original type ... maybe?
EDIT: To clarify, basically, I'm passing &out to a function and it needs to be its original type by the time it reaches another inner function call.
Example code:
// NOTE: This is sort of pseudo-Golang code, not meant to be compiled or taken too seriously.
func PrepareTwoDifferentThings(keyA string, keyB string) {
var somethingA TypeA;
var somethingB TypeB;
loadFromCache(keyA, &somethingA, nil);
loadFromCache(keyB, &somethingB, nil);
fmt.Printf("Somethings: %v, %v", somethingA, somethingB);
}
func loadFromCache(key string, isNew, out interface {}, saveNewData interface {}) {
if err := cache.load(key, &out); err!=nil { // NOTE: Current issue is that this expects "&out" to be `TypeA`/`TypeB` not "interface {}", but I don't want to copy and paste this whole function's worth of code or whatever.
panic("oh no!");
}
if (saveNewData!=nil) {
cache.save(key, saveNewData); // This doesn't seem to care if "saveNewData" is "interface {}" when saving, but later cache fetches above using the "load()" method to an "interface {}"-typed `&out` parameter throw an exception that the "interface {}" type on `&out` does not match the original when it was saved here (`TypeA`/`TypeB`).
}
}
To change the type of an interface into its rightful type, you can use type assertions:
package main
import r "reflect"
type A struct {
Name string
}
func main() {
// No pointer
aa := A{"name"}
var ii interface{} = aa
bb := ii.(A)
// main.A
// Pointer
a := &A{"name"}
var i interface{} = a
b := *i.(*A)
// main.A
c := i.(*A)
// *main.A
d := r.Indirect(r.ValueOf(i)).Interface().(A)
// main.A
}
Playground 1
When using type assertions, you have to know the underlying type of your interface. In Go, there is no way to use type assertion with a dynamic type. reflect.Type is not a type, it's an interface representing a type. So no, you can't use it this way.
If you have several type possibilities, the solution is the type switch:
package main
import "fmt"
type TypeA struct {
A string
}
type TypeB struct {
B string
}
func doSomethingA(t TypeA) {
fmt.Println(t.A)
}
func doSomethingB(t TypeB) {
fmt.Println(t.B)
}
func doSomething(t interface{}) {
switch t := t.(type) {
case TypeA:
doSomethingA(t)
case TypeB:
doSomethingB(t)
default:
panic("Unrecognized type")
}
}
func main() {
a := TypeA{"I am A"}
b := TypeB{"I am B"}
doSomething(a)
// I am A
doSomething(b)
// I am B
}
Playground 2
It turns out that using JSON instead of Gob for serialization avoids the error that I was encountering entirely. Other functions can handle passing into interfaces, etc.