GO Golang : anonymous structs & Reflection combination - reflection

After reading the laws of reflection about 10 times the last 2 months. Developing with it for the same amount of time, i have to say it is a cool and understandable language... at least to an certain level.
My background as PHP & Javascript developer are giving me an hard time to comprehend the following example:
package main
import(
"fmt"
"reflect"
)
func test1(){
type template struct {
Title string
Body string
}
data := []template{
{ Title : "About page", Body : "Body info"},
{ Body : "About page 2 ", Title : "Body info 2"},
}
fmt.Println( "-- TEST ONE --" )
fmt.Println( data[0].Title )
}
func test2(){
data := []struct{
Title string
Body string
}{
// Assign with the actual order
{ "About page", "Body info"},
// Key => Val assignment (Pretty cool)
{ Body : "Body info 2 ", Title : "About page 2"},
}
fmt.Println( "-- TEST TWO --" )
fmt.Println( data[1].Title )
}
func test3(){
type template struct {
Title string
Body string
}
Amap := map[string]interface{}{
"template" : template{},
}
w := reflect.ValueOf(Amap["template"])
x := w.Type()
y := reflect.TypeOf(w.Interface())
z := reflect.TypeOf(Amap["template"])
fmt.Printf("%+v\n", x) // main.template
fmt.Printf("%+v\n", y) // main.template
fmt.Printf("%+v\n", z) // main.template
/*
var data = struct{
// none of the above can be place in here.... ( (w|x|y|z) is not a type)
}{ "About page", "Body info"}
*/
ww := reflect.New(z)
xx := ww.Interface()
tt := reflect.TypeOf(xx)
/*
// none of the above can be used this way....
var data = ww{
}{ "About page", "Body info"}
*/
fmt.Println( "-- TEST THREE --" )
fmt.Println( data.Title )
}
func main(){
test1()
test2()
test3()
}
The above example test1() and test2() work as expected. I wanted to push it even further with test3() but without success. The only way i could think of making it work was with an type switch..
But since I am trying things out I'd like to know if :
Is there an way to cast an anonymous struct from an reflection value without type checking the actual struct that is being reflected
Could you show me an working solution to either one of the 2 commented out code blocks from test3()

Is there a way to cast 1 an anonymous struct from an reflection value without type checking [2] the actual struct that is being reflected?
There is no casting in Go. If you mean a conversion then you're missing a predicate: convert to what?
Type checking is something a compiler does to a program. This sentence does not make sense.
Could you show me a working solution to either one of the 2 commented out code blocks from test3()
That's simple, just write:
var data = struct{string, string}{"About page", "Body info"}
If you mean to build/create/assemble a struct type on runtime I'll have to disappoint you; that's not possible.
Edit (11. Feb 2015): building struct types (as well as arrays, funcs and interfaces) on runtime by means of reflection is being implemented.

Related

Dynamic argument and Generic type

I have following code:
package main
import (
"fmt"
)
func test(data interface{}) {
data = "123"
}
func main() {
t := "org"
test(&t)
fmt.Println(t)
e := 1
test(&e)
fmt.Println(e)
}
I tried to add pointer to *interface{} but it throws errors, how can I assign string "test" to t when I print it? right now t will be printed out as "org"
I am asking because I am not sure how I can use dynamic type here, for instance, josn.Unmarshal(data []byte, v interface{}) I used this function, and it can convert databyte to any type we want as long as we pass the reference.
I think you are expecting interface to be much more magic than it actually is.
Consider this variant of your program:
package main
import (
"fmt"
)
func test(p *string) {
s := "test"
p = &s
}
func main() {
t := "org"
test(&t)
fmt.Println(t)
}
Do you expect this to print test? If so, we have a bigger problem. :-) If not, why do you expect the version with p interface{} to change t when assigning directly to p?
If we change test to write through *p:
func test(p *string) {
*p = "test"
}
the program does print test, as you expected.
All that remains now is to handle the case when p is declared instead as data interface{}. As in bserdar's answer, you must first extract the underlying *string pointer from the interface object in data. You can then use that pointer to set main's variable t. You could do this with two steps:
func test(data interface{}) {
p := data.(*string)
*p = "test"
}
for instance, or you can do it all in one line.
You are setting the interface, not the underlying value. Instead you should do
func test(data interface{}){
*data.(*string) = "aaa"
}
That is, first get the underlying string pointer, then set the string pointed by it.

How to convert interface to struct

Here is the simplified code of a cache. Suppose Container placed in a package, so it don't know about Member.
While I wanna store instances of Member in Container, So I store an empty instance of Member in Container as outerType.
In the Container->GetMysql, I fill a new variable by test values (but, in real world, It fill by data of database, dynamically).
then in the function Put, I store data in items as Cache for next uses. In the Get I get the data stored in the items.
Before this every thing is fine. My problem is where i want to convert result of Get to type of Member m = res.(Member) . How Can I convert it to an instance of Member
I found many question about this subject, but none of them solved my problem
For more detail: I want the Get return data with its pointer of where it stored in items. So if I get some variable of same member, an change in one are shown in others
package main
import (
"fmt"
"reflect"
)
type Member struct {
Id int
Name string
Credit int
Age int
}
type Container struct {
outerType interface{}
items map[string]*interface{}
}
func (cls *Container)GetMysql(s string, a int64) interface{}{
obj := reflect.New(reflect.TypeOf(cls.outerType))
elem := obj.Elem()
//elem := reflect.ValueOf(o).Elem()
if elem.Kind() == reflect.Struct {
f := elem.FieldByName("Name")
f.SetString(s)
f = elem.FieldByName("Credit")
f.SetInt(a)
}
return obj.Interface()
}
func (cls *Container)Get(value string) *interface{}{
return cls.items[value]
}
func (cls *Container)Put(value string, a int64) {
res := cls.GetMysql(value, a)
cls.items[value] = &res
}
func main() {
c := Container{outerType:Member{}}
c.items = make(map[string]*interface{})
c.Put("Jack", 500)
res := c.Get("Jack")
fmt.Println(*res)
m := &Member{}
m = res.(Member) // Here is the problem. How to convert ?
fmt.Println(m)
}
You should hardly ever use pointer to interface. My advice is to never use it, when you'll need it, you'll know.
Instead if you need a pointer to something (so you can have the same pointer at multiple places, and so modifying the pointed value somewhere, it will have effect on the others), "wrap the pointer" in the interface value.
So first modify the items field so that it stores interface{} values instead of pointers:
items map[string]interface{}
This means no restriction: you can pass and store pointers, that's not a problem.
Next modify Get() to return interface{}:
func (cls *Container) Get(value string) interface{}{
return cls.items[value]
}
And also in Put(), don't take the address of an interface{}:
func (cls *Container) Put(value string, a int64) {
res := cls.GetMysql(value, a)
cls.items[value] = res
}
And you have to type-assert *Member from the values returned by Get().
And now testing it:
c := Container{outerType: Member{}}
c.items = make(map[string]interface{})
c.Put("Jack", 500)
res := c.Get("Jack")
fmt.Println(res)
m := res.(*Member) // Here is the problem. How to convert ?
fmt.Println(m)
Output (try it on the Go Playground):
&{0 Jack 500 0}
&{0 Jack 500 0}
Now if you would modify a field of m:
m.Credit = 11
And then get the value form the cache:
fmt.Println(c.Get("Jack"))
We'll see the modified value, even though we did not call Put() (try it on the Go Playground):
&{0 Jack 11 0}

Print an array of empty interfaces in golang?

I have a struct with a field of the form field []interface{}. If I print the field, I get back a pointer reference. If I try to dereference the field, I get an error "invalid indirect".
The code is below:
type MyType struct {
field []interface{}
}
myType := //create a MyType. Field is just an array of numbers
println(myType.field) // prints a pointer reference, ex: [1/1]0xc420269aa0
println(*(myType.field)) // doesn't compile
How do I print the values in myType.field?
The answer is to loop through the array, or even better, use fmt.Println.
func dump(items []interface{}) {
for i := 0; i < len(items); i++ {
fmt.Println(items[i])
}
}
// OR
fmt.Println(items)
another way you could use
https://play.golang.org/p/4lLQ4Gb2S0m
package main
import (
"encoding/json"
"fmt"
)
func main() {
fmt.Println(dump(new(bool)))
fmt.Println(dump([]interface{}{new(bool), new(string)}))
}
func dump(x interface{}) string {
json, err := json.MarshalIndent(x, "", " ")
if err != nil {
panic(err)
}
return string(json)
}
// Outputs:
// false
// [
// false,
// ""
// ]
Array interfaces can be printed as follows
questionSet := []interface{}{}
// ... code to fillup the question set
fmt.Printf("%t", questionSet)
and here is the result
[%!t(*domain.Question=&{First Economics question 3
[{Economics option 1 for student false}
{Economics option 2 for student false}
{Economics option 3 for student true}
{Economics option 4 for student false}]
[{Economics first topic} {Economics second topic}]})
%!t(*domain.Question=&{second Question 4
[{Qs2 Option 1 for student false}
{Qs2 Option 2 for student false}
{Qs2 Option 3 for student false}
{Qs2 Option 4 for student false}]
[{third topic} {fourth topic}]})]
The output here is not very pretty but at least you can see the result and extract your relevant information for further process.
In the above result domain.Question is a struct and here is the complete struct for your reference. Hope this will help you to understand better.
type Question struct {
Questions string `json:"questions,omitempty" bson:"questions"`
Marks string `json:"marks,omitempty" bson:"marks"`
Options []QuestionOptions `json:"options,omitempty" bson:"options"`
Topics []QuestionTopic `json:"topics,omitempty" bson:"topics"`
}
type QuestionOptions struct {
Option string `json:"option" bson:"option"`
Correct bool `json:"correct" bson:"correct"`
}
type QuestionTopic struct {
Topic string `json:"topic" bson:"topic"`
}
Consider that the verb %t is designed to print boolean (see the doc overview at https://golang.org/pkg/fmt/), as such, while using it to dump the content of a value works as of today, it is not the behavior intended by go authors, and as such, this behavior might change in the future.
Peace,

Passing an struct to a Post martini routine

I have an issue using this statement
m.Post(Model, binding.Form(Wish), func(wish Wish, r render.Render, db *mgo.Database) {
This worked fine if I use the struct define inside the prog like
m.Post(Model, binding.Form(Wish1{}) , func(wish Wish1, r render.Render, db *mgo.Database) {
but I need this to be an independent package.
I get "Wish is not a type" wish is the return of the binding function.
This worked with a primary Type struct. I am passing the strut as a interface{}
I am using GO with Martini.Classic() It is really complicated for me to change Martini or Binding package. Any suggestions.
This is the all code
package chlistpkg
import (
"github.com/codegangsta/martini"
"github.com/codegangsta/martini-contrib/binding"
"github.com/codegangsta/martini-contrib/render"
"labix.org/v2/mgo"
"time"
"fmt"
"html/template"
"reflect"
"adminStruct"
)
just to show the struct that I need to pass as to routine Doall
type Wish1 struct {
Name string `form:"name"`
Description string `form:"description"`
AnyDate time.Time `form:"anydate"`
Active bool `form:"active"`
Number int `form:"number"`
NumDec float32 `form:"numDec"`
}
DB Returns a martini.Handler
func DB() martini.Handler {
session, err := mgo.Dial("mongodb://localhost")
if err != nil {
panic(err)
}
return func(c martini.Context) {
s := session.Clone()
c.Map(s.DB("advent2"))
defer s.Close()
c.Next()
}
}
GetAll returns all Wishes in the database
func GetAll(db *mgo.Database, entList interface{}) interface{} {
db.C("wishes").Find(nil).All(entList)
fmt.Println("GettAll entList =", entList)
return entList
}
func Doall(Model string, Wish interface{}, Wish2 interface{}, Wishlist interface{} ) {
m := martini.Classic()
fmt.Println ("martini.Classic =", m)
m.Use(martini.Static("images")) // serve from the "images" directory as well
m.Use(render.Renderer(render.Options{
Directory: "templates",
Layout: "layout",
}))
m.Use(DB())
m.Get(Model, func(r render.Render, db *mgo.Database) {
r.HTML(200, "lista4", GetAll(db, Wishlist))
})
binding does not take a pointer. I have to pass the struct by reference on "Wish"
the issue is the return on "wish Wish" I got an error Wish is not a type
at compilation time
m.Post(Model, binding.Form(Wish), func(wish Wish, r render.Render, db *mgo.Database) {
fmt.Println("Input wish =", wish)
db.C("wishes").Insert(wish)
r.HTML(200, "lista4", GetAll(db, Wishlist))
})
m.Run()
Thanks in advance
Luis
The reason you are getting an error is that you have called your type Wish1 (with a numerical 1) but you are referring to the Wish type (which does not exist!) in your code.
Change your struct to be:
// Note: "Wish", not "Wish1"
type Wish struct {
Name string `form:"name"`
Description string `form:"description"`
AnyDate time.Time `form:"anydate"`
Active bool `form:"active"`
Number int `form:"number"`
NumDec float32 `form:"numDec"`
}
If you want to put your type into another package (tip: don't overdo the sub-packages), then it will need to become a pkgname.Wish as names are fully qualified.
Added
After a second look, you're also messing things up here:
func Doall(Model string, Wish interface{}, Wish2 interface{}, Wishlist interface{} ) {
m := martini.Classic()
fmt.Println ("martini.Classic =", m)
m.Use(martini.Static("images")) // serve from the "images" directory as well
Your parameter list needs to provide a name for each type; you can't pass Wish interface{} as a parameter as Wish is a type, not a variable name.
You should either:
func DoAll(model string, wish interface{}, wish2 interface{}, wishList interface{}) { ... }
Or, better still, stop using interface{} like this and write:
func DoAll(model string, wishList []Wish, wishes... Wish) { ... }
However, your DoAll function does not seem to be referenced elsewhere, and is creating its own Martini instance. I highly suggest thinking about why things are "split out" like this if you're just starting out. Keep it simple - e.g.
func main() {
m := martini.Classic()
m.Use(martini.Static("images"))
m.Use(DB())
m.Use(render.Renderer(render.Options{...}))
// No need for an anonymous function, which just adds clutter
m.Get("/wishes/all", GetAllWishes)
// Same goes for here
m.Post("/wishes/new", PostWish)
m.Run()
}
PS: I've fixed the formatting of your code, as it has a lot of unnecessary spacing before/after parenthesis. Make sure to use gofmt, which is included with the Go install and can be hooked into most popular editors.

Get struct field tag using Go reflect package

Is it possible to reflect on a field of a struct, and get a reference to its tag values?
For example:
type User struct {
name string `json:name-field`
age int
}
// ...
user := &User{"John Doe The Fourth", 20}
getStructTag(user.name)
// ...
func getStructTag(i interface{}) string{
//get tag from field
}
From what I can see, the usual way to do this is to range over typ.NumField(), and then call field.Tag.Get("tagname").
However, in my use-case, it would be much better to not have to pass the whole struct in.
You don't need to pass in the whole struct, but passing in the value of one of the fields is not sufficient.
In your example user.name field is just a string - the reflect package will have no way of correlating that back to the original struct.
Instead, you need to pass around the reflect.StructField for the given field:
field, ok := reflect.TypeOf(user).Elem().FieldByName("name")
…
tag = string(field.Tag)
Note: we use Elem above because user is a pointer to a struct.
You can play with an example here.
Modifying the above answer can give value of a specific tag
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string `json:"name_field"`
Age int
}
func main() {
user := &User{"John Doe The Fourth", 20}
field, ok := reflect.TypeOf(user).Elem().FieldByName("Name")
if !ok {
panic("Field not found")
}
fmt.Println(getStructTag(field, "json")) //name_field
}
func getStructTag(f reflect.StructField, tagName string) string {
return string(f.Tag.Get(tagName))
}
https://play.golang.org/p/Sb0i7za5Uow
Clean way to list all tags from a struct (using external lib).
External lib: https://github.com/fatih/structs
Example: https://go.dev/play/p/C_yXMdbFYAq
package main
import (
"fmt"
"github.com/fatih/structs"
)
type User struct {
Name string `json:"name_field"`
Age int `json:"age_field"`
}
func main() {
user := &User{}
fields := structs.Fields(user)
for _, field := range fields {
tag := field.Tag("json")
fmt.Println(tag)
}
}
Result:
name_field
age_field

Resources