Wrong type of reflected struct - reflection

I have 2 different packages(pkg1, pkg2), in first i have code that calls function from another package
file#1
package pkg1
import "pkg2"
import "reflect"
type User struct {
name string
...
}
func main() {
fmt.Println(reflect.TypeOf((*User)(nil)) //=> *User
pkg2.RegisterStruct(reflect.TypeOf((*User)(nil))
//pkg2.RegisterStruct(reflect.TypeOf(&User{}) // also tried this way
}
file#2
package pkg2
import "reflect"
func RegisterStruct(u interface{}) { // also tried to have argument type as reflect.Type
fmt.Println(u) //=> *reflect.rtype
}
Why type was reflect.rtype instead of *User ?
And how do i correctly pass type to another pkg?

The reflect.TypeOf() returns a reflect.Type now you are doing two completely different things with: In the first call to Println (the "correct" one) this reflect.Type is wrapped inside an interface{} (during the call to Println) while in the second (the "wrong" one) you wrap the reflect.Type inside an interface{} while calling RegisterSturct and you then rewrap it once more inside an additional interface{} while calling Println. Println just removes one layer of interface{}-wrapping.
Sorry, this is nonsense. I'll have to think a bit more. Would delete if possible.

Related

Convert named-type map[string]string to plain one in Golang

I have a map of type set, which is actually a map[string]string. However, passing it to a function which accepts a map[string]string fails, because Go does not recognize set as one.
However, I fail to convince the compiler it is one. Is there any way to resolve this, without looping and copying?
package main
import (
"fmt"
)
type name string
type field string
type set map[name]field // map[string]string after all
type plain map[string]string // also map[string]string
func main() {
var typed = set{"hi": "ho"} // map[string]string?
back := plain(typed) // cannot convert typed (type set) to type plain
back := typed.(plain) // invalid type assertion: typed.(plain) (non-interface type set on left)
echo(back)
}
func echo(in map[string]string) {
fmt.Println(in)
}
You could do this using the unsafe package.
Note: I don't think this would necessarily be a good idea, and probably the right way would be to just iterate and copy, but since it does answer the question asked...
var typed = set{"hi": "ho"} // map[string]string?
p := unsafe.Pointer(&typed)
var back plain
back = *(*plain)(p)
Playground: https://play.golang.org/p/yienSuJSnQU

Confusion with pointer, slices and interface{} in function arguments in go

I've been reading about how Go passes arguments to functions via pointer vs. value. I've been reading about the interface type. And I've been tampering with the reflect package. But clearly, I still don't understand how it all works because of this example code here:
package main
import (
"reflect"
"fmt"
)
type Business struct {
Name string
}
func DoSomething(b []Business) {
var i interface{}
i = &b
v := reflect.ValueOf(i).Elem()
for c:=0 ;c<10; c++ {
z := reflect.New(v.Type().Elem())
s := reflect.ValueOf(z.Interface()).Elem()
s.Field(0).SetString("Pizza Store "+ fmt.Sprintf("%v",c))
v.Set(reflect.Append(v, z.Elem()))
}
fmt.Println(b)
}
func main() {
business := []Business{}
DoSomething(business)
}
When I run this code, it will print a list of ten Business structs with the Business.Name of Pizza 0 to 9. I understand that in my example, that my DoSomething function received a copy of the slice of business, and hence, the business variable in my main function remains unaffected by whatever DoSomething does.
What I did next was change my func DoSomething(b []Business) to func DoSomething(b interface{}). Now when I try to run my script, I get the run time error of panic: reflect: Elem of invalid type on on the line z := reflect.New(v.Type().Elem())
I noticed that with DoSomething(b []Business), the variable i == &[]. But with DoSomething(b interface{}), the variable i == 0xc42000e1d0. Why is the variable i different under these two circumstances?
Your debugger most likely uses (or at least follows) the default formatting rules of the fmt package:
For compound objects, the elements are printed using these rules, recursively, laid out like this:
struct: {field0 field1 ...}
array, slice: [elem0 elem1 ...]
maps: map[key1:value1 key2:value2 ...]
pointer to above: &{}, &[], &map[]
In your first case i holds a value of type *[]Business. So if a value being printed (or inspected) is a pointer to slice, it is printed as &[values].
In your second case i holds a pointer to an interface{} value, which is of type *interface{}. When printing a value of this type, the default %p format is used which simply prints the memory address as a hexadecimal value prefixed with 0x.

golang get the reflect.Type of a type

Is it possible and how to get the reflect.Type of a type without creating an object from the type and calling on it reflect.TypeOf(obj)
What in java will be: MyType.class
You can achieve this without an instantiation with the following syntax;
package main
import (
"fmt"
"reflect"
)
type Test struct {
}
func main() {
fmt.Println(reflect.TypeOf((*Test)(nil)).Elem())
}
play; https://play.golang.org/p/SkmBNt5Js6
Also, it's demonstrated in the reflect example here; https://golang.org/pkg/reflect/#example_TypeOf
No you can't have it directly, because in Go structs have no accessible fields to get their type.
One may think of tweaking it by doing the following:
type object struct {}
func main() {
var obj object
t := reflect.TypeOf(object)
fmt.Println(t)
// main.object
}
However, in Go every variable is initialized with its zero value, so this is perfectly equivalent to:
t := reflect.TypeOf(object{})
// main.object
If you look at Golang's source code, you'll see that reflect.Type is an interface implemented differently according to types, however you do not have access to those informations.
But, what you can do is get the type of a pointer to the struct and from there, get the actual type. The process is the same, except that a pointer's zero value is nil, so it takes less time to instantiate:
func main() {
ptr_t := reflect.TypeOf((*object)(nil))
fmt.Println(ptr_t)
// *main.object
t := ptr_t.Elem()
fmt.Println(t)
// main.object
}

Why is there a "-fm" suffix when getting a function's name in Go?

For the snippet below (runnable via the Go Playground),
package main
import (
"fmt"
"net/http"
"reflect"
"runtime"
)
type User struct{}
var u = &User{}
func (_ User) DummyHandler(w http.ResponseWriter, r *http.Request) {}
func funcName(i interface{}) {
p := reflect.ValueOf(i).Pointer()
n := runtime.FuncForPC(p).Name()
fmt.Println(n)
}
func main() {
funcName(u.DummyHandler)
}
The output is main.(User).DummyHandler-fm.
Why is there a -fm at the end of the function name?
Turns out u.DummyHandler is a method value and the compiler implements methods by creating a function closure and modifying the function name. To quote Ian here:
This seems to have become -fm on tip, by the way.
Your code is getting a method value. p.beHappy is the beHappy method
bound to the specific value of p. That is implemented by creating a
function closure, and the code for that closure needs a name. The
compiler happens to make that name by sticking fm on the end, but it
could be anything that won't conflict with any other function name.
There isn't any way to name that function in Go, so the name is
irrelevant for anything other than the debugger or, as you see,
FuncForPC.
It seems like a better way to get a method's name is to reference the method directly, like so:
func main() {
funcName((User).DummyHandler)
}
This will output main.User.DummyHandler.

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.

Resources