Dynamic argument and Generic type - pointers

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.

Related

Print a type without using reflrect and create new object

In below code, in order to show the expected type, I have to create a new object and call reflect.TypeOf on it.
package main
import (
"fmt"
"reflect"
)
type X struct {
name string
}
func check(something interface{}) {
if _, ok := something.(*X); !ok {
fmt.Printf("Expecting type %v, got %v\n",
reflect.TypeOf(X{}), reflect.TypeOf(something))
}
}
func main()
check(struct{}{})
}
Perhaps that object creation is not an overhead, but I still curious to know a better way. Are there something like X.getName() or X.getSimpleName() in java?
To obtain the reflect.Type descriptor of a type, you may use
reflect.TypeOf((*X)(nil)).Elem()
to avoid having to create a value of type X. See these questions for more details:
How to get the string representation of a type?
Golang TypeOf without an instance and passing result to a func
And to print the type of some value, you may use fmt.Printf("%T, something).
And actually for what you want to do, you may put reflection aside completely, simply do:
fmt.Printf("Expecting type %T, got %T\n", (*X)(nil), something)
Output will be (try it on the Go Playground):
Expecting type *main.X, got struct {}
Using reflects is almost always a bad choice. You can consider using one of the following ways
Use switch
If you want to control the flow depending on the type you can use the switch construction
func do(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("Twice %v is %v\n", v, v*2)
case string:
fmt.Printf("%q is %v bytes long\n", v, len(v))
default:
fmt.Printf("I don't know about type %T!\n", v)
}
}
Use fmt package
If you want only to display its type you can always use the fmt package
i := 1000
fmt.Printf("The type is %T", i)

Difference between &Struct{} vs Struct{}

Is there a reason why I should create a struct using &StructName{} instead of Struct{}? I see many examples using the former syntax, even in the Effective Go Page but I really can not understand why.
Additional Notes:
I'm not sure whether I explained my problem well with these two approaches so let me refine my question.
I know that by using the & I will recieve a pointer instead of a value however I would like to know why would I use the &StructName{} instead of the StructName{}. For example, is there any benefits of using:
func NewJob(command string, logger *log.Logger) *Job {
return &Job{command, logger}
}
instead of:
func NewJob(command string, logger *log.Logger) Job {
return Job{command, logger}
}
Well, they will have different behavior. Essentially if you want to modify state using a method on a struct, then you will need a pointer, otherwise a value will be fine. Maybe an example will be better:
package main
import "fmt"
type test_struct struct {
Message string
}
func (t test_struct)Say (){
fmt.Println(t.Message)
}
func (t test_struct)Update(m string){
t.Message = m;
}
func (t * test_struct) SayP(){
fmt.Println(t.Message)
}
func (t* test_struct) UpdateP(m string) {
t.Message = m;
}
func main(){
ts := test_struct{}
ts.Message = "test";
ts.Say()
ts.Update("test2")
ts.Say() // will still output test
tsp := &test_struct{}
tsp.Message = "test"
tsp.SayP();
tsp.UpdateP("test2")
tsp.SayP() // will output test2
}
And you can run it here go playground
Assuming you know the general difference between a pointer and a value:
The first way allocates a struct and assigns a pointer to that allocated struct to the variable p1.
p1 := &StructName{}
The second way allocates a struct and assigns a value (the struct itself) to the variable s.
Then a pointer to that struct may be assigned to another variable (p2 in the following example).
s := StructName{}
p2 := &s

How to create slice of struct using reflection?

I need to create a slice of struct from its interface with reflection.
I used Reflection because do not see any other solution without using it.
Briefly, the function receives variadic values of Interface.
Then, with reflection creates slice and passes it into another function.
Reflection asks to type assertion
SliceVal.Interface().(SomeStructType)
But, I cannot use it.
Code in playground http://play.golang.org/p/EcQUfIlkTe
The code:
package main
import (
"fmt"
"reflect"
)
type Model interface {
Hi()
}
type Order struct {
H string
}
func (o Order) Hi() {
fmt.Println("hello")
}
func Full(m []Order) []Order{
o := append(m, Order{H:"Bonjour"}
return o
}
func MakeSlices(models ...Model) {
for _, m := range models {
v := reflect.ValueOf(m)
fmt.Println(v.Type())
sliceType := reflect.SliceOf(v.Type())
emptySlice := reflect.MakeSlice(sliceType, 1, 1)
Full(emptySlice.Interface())
}
}
func main() {
MakeSlices(Order{})
}
You're almost there. The problem is that you don't need to type-assert to the struct type, but to the slice type.
So instead of
SliceVal.Interface().(SomeStructType)
You should do:
SliceVal.Interface().([]SomeStructType)
And in your concrete example - just changing the following line makes your code work:
Full(emptySlice.Interface().([]Order))
Now, if you have many possible models you can do the following:
switch s := emptySlice.Interface().(type) {
case []Order:
Full(s)
case []SomeOtherModel:
FullForOtherModel(s)
// etc
}

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.

Go: edit in place of map values

I wrote a simple program using the Go Playground at golang.org.
The output is obviously:
second test
first test
Is there a way to edit the map value in place? I know I can't take the andress of a.Things[key]. So, is setting a.Things[key] = firstTest the only way to do it? Maybe with a function ChangeThing(key string, value string)?
You could do it by making the values of your map pointers to another struct.
http://play.golang.org/p/UouwDGuVpi
package main
import "fmt"
type A struct {
Things map[string]*str
}
type str struct {
s string
}
func (a A) ThingWithKey(key string) *str {
return a.Things[key]
}
func main() {
variable := A{}
variable.Things = make(map[string]*str)
variable.Things["first"] = &str{s:"first test"}
firstTest := variable.ThingWithKey("first")
firstTest.s = "second test"
fmt.Println(firstTest.s)
fmt.Println(variable.ThingWithKey("first").s)
}
You can use a pointer as the map value http://play.golang.org/p/BCsmhevGMX

Resources