How does value change in Golang Map of interface - dictionary

This is the code base -
https://go.dev/play/p/BeDOUZ9QhaG
Output -
map[something:map[ACM:34.12 age:12 dune:dune]]
How does changing values in t variable affect in x?
package main
import "fmt"
func main() {
x: = make(map[string] interface {}, 10)
x["something"] = map[string] interface {} {
"dune": "dune", "age": 12
}
t: = x["something"].(map[string] interface {})
t["ACM"] = 34.12
fmt.Println(x)
}

Map types are reference types, like pointers or slices,
so this line
t := x["something"].(map[string]interface{}) t["ACM"] = 34.12 fmt.Println(x) }
is just a shallow copy creating alias for the existing map you created above in x variable ,so they are pointing to same memory address where the original map you created exists.
See for reference -https://go.dev/blog/maps

Related

Create map or objects from struct with additional properties as key

i've struct which build like following
type RTB struct {
ID string
Modules []*Modules
Req []*Req
}
Now inside module I've the following
type Modules struct {
Name string
Type string
Path string
Id string
}
Now I've the object of RTB in the memory and I want to create map (that I can loop on it si object which will be like following:
NewObject {
Type string//the value from the module struct
Modules []*Modules // From the rtb struct
}
of course I can loop on it (if there is not more elegant way...) and create new struct (like the new object) and fill the data from both structs, but there is better way in Golang like map to store this data?
You have to use a loop to go over the modules and build a map from it. No easier way. If you need this functionality in multiple places, put it into a utility function and call that wherever needed.
Example building the map:
rtb := &RTB{
Modules: []*Modules{
{Name: "n1", Type: "t1"},
{Name: "n2", Type: "t1"},
{Name: "n3", Type: "t2"},
},
}
m := map[string][]*Modules{}
for _, mod := range rtb.Modules {
m[mod.Type] = append(m[mod.Type], mod)
}
// Verify result (JSON for "nice" outpout):
fmt.Println(json.NewEncoder(os.Stdout).Encode(m))
Output:
{"t1":[{"Name":"n1","Type":"t1"},{"Name":"n2","Type":"t1"}],"t2":[{"Name":"n3","Type":"t2"}]}
<nil>
If you want a slice of NewObject instead of the map, you can build that like this:
// m is the map built above.
var newObjs []*NewObject
for k, v := range m {
newObjs = append(newObjs, &NewObject{
Type: k,
Modules: v,
})
}
fmt.Println(json.NewEncoder(os.Stdout).Encode(newObjs))
Output:
[{"Type":"t1","Modules":[{"Name":"n1","Type":"t1"},{"Name":"n2","Type":"t1"}]},{"Type":"t2","Modules":[{"Name":"n3","Type":"t2"}]}]
<nil>
Try the examples on the Go Playground.

How to implement interfaces in following code?

I have the following code and I want to use interfaces:
Current code:
import (
"github.com/dorzheh/deployer/ui/dialog_ui"
. "github.com/dorzheh/go-dialog"
)
// all methods in https://github.com/dorzheh/deployer/blob/master/ui/dialog_ui/dialog_ui.go#L28
type Pb struct {
sleep time.Duration
step int
}
type DialogUi struct {
*Dialog //The source is https://github.com/dorzheh/go-dialog/blob/master/dialog.go#L34
Pb *Pb
}
I am trying to implement interfaces this way:
import (
"testing"
// . "github.com/dorzheh/go-dialog"
//"github.com/dorzheh/deployer/ui/dialog_ui"
)
type PBifaceT interface {
Step() int
}
type TestDialogUiT struct {
Pb *PBifaceT
}
func TestUiValidateUser(t *testing.T) {
x := dialog_ui.TestDialogUiT{}
PbPb := ImplPBifaceT{}
x.Pb = PbPb
parentId := x.Pb.Step()
t.Logf(fmt.Sprintf("%v", parentId))
}
I've made a playground. As you can see it runs in the following error:
prog.go:23: cannot use PbPb (type ImplPBifaceT) as type *PBifaceT in assignment:
*PBifaceT is pointer to interface, not interface
prog.go:25: x.Pb.Step undefined (type *PBifaceT is pointer to interface, not interface)
I tried to convert them in this playground:
func NewD() *PBifaceT {
// var err error
var res =new(ImplPBifaceT)
return (*PBifaceT)(res)
}
func main() {
x := TestDialogUiT{}
x.Pb = NewD()
parentId := x.Pb.Step()
fmt.Sprintf("%v", parentId)
}
The issue:
prog.go:23: cannot convert res (type *ImplPBifaceT) to type *PBifaceT
prog.go:30: x.Pb.Step undefined (type *PBifaceT is pointer to interface, not interface)
Are you sure you need your PbĀ field as a *PBifaceT.
If you keep it as a
type TestDialogUiT struct {
Pb *PBifaceT
}
and you do
x := TestDialogUiT{}
PbPb := ImplPBifaceT{}
x.Pb = PBifaceT(PbPb)
parentId := x.Pb.Step()
fmt.Printf("%v", parentId)
It works properly..
Take a look at this playground and see if it can help.
I'd suggest you to take a look at this tutorial and this doc.
I'd suggest you also to read this SO answer which explains a bit of how you shouldn't want to use interface pointers.
Background: In Go you pass around a pointer to something because of two reasons:
1) You want because your struct is really large and you want to avoid copying
2) you need to because the calee wants to modify the original (this is typical for methods with a pointer receiver). Now an interface value is really tiny (just two words) so reason 1 to pass a pointer to an interface value does not apply.
Reason 2 does not apply in most cases as passing a pointer to an interface value will allow you to change the interface value itself, but most often you would like to modify the value stored inside the interface value. This value stored inside the interface value often is a pointer value which allows to change the value of a struct by calling methods on an interface value which wrapps a pointer to this struct. This sounds complicated but isn't: The novice Go programmer just doesn't use pointers to interfaces (as this won't do any good) and the experienced Go programmer doesn't use pointers to interfaces (as it won't do much good) unless he needs to modify an interface value, typically during reflection.
You can use Pb by link, you were just missing pointer reference while assigning.
package main
import (
"fmt"
)
type PBifaceT interface {
Step() int
}
type TestDialogUiT struct {
Pb PBifaceT
}
type ImplPBifaceT struct {
}
func (m *ImplPBifaceT) Step() int {
return 0
}
func main() {
x := TestDialogUiT{}
PbPb := &ImplPBifaceT{}
x.Pb = PbPb
parentId := x.Pb.Step()
fmt.Printf("%v", parentId)
}
Please refer this playground link: https://play.golang.org/p/N7quQFpYU0
Changes were at line 12, 17, 23 & 27.
Do not use pointer to interface unless you are sure that's what you want, see Pb *PBifaceT inside TestDialogUiT. If you change it to just Pb PBifaceT your playground link just works.
An interface is already a pointer.

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.

Value receiver of struct

Can someone explain to me why the output of r.a is empty as I have added a value of 2 into the list?
package main
import (
"fmt"
)
func main() {
var r R
r.b = make(map[int]int)
r.add()
fmt.Println(r) // outputs {[] map[2:2]}
}
type R struct {
a []int
b map[int]int
}
func (r R) add() {
r.a = append(r.a, 2)
r.b[2] = 2
}
A short excerpt from the Tour of Go states that:
Methods with pointer receivers can modify the value to which the
receiver points [...]. Since methods often need to modify their
receiver, pointer receivers are more common than value receivers.
Why is r.b shown correctly while r.a is not modified at all?
As already stated in my answer below, your add() method is a value receiver. Therefore, it will take your initialized struct (i.e. r), copy it and then modify it accordingly. Because you have initialized a new map under r.b in your main() function, here only the reference to this map is copied but not the whole map. Therefore, the manipulation on the map works but not on the slice r.a. But why does r.a not change at all? That's because append(), which is located in the add() method, stores a new slice header under your a property, and is pointing to a different section of the underlying array. At the end, your value receiver method add() made a copy of r, set a new slice header under the property a, and never changed the original struct r, that has been defined in the main() function as it was copied through the value receiver method add().
In your case the add() method is a so called value receiver method that cannot do any manipulation on your defined struct r located in the main() function directly, but copies it and does the manipulation afterwards. Therefore, you need to turn your add() method into a pointer receiver method just like this:
func (r *R) add() {
r.a = append(r.a, 2)
r.b[2] = 2
}
Now the method is taking the actual reference of your struct r, that is initiated in the main() function, and modifies it accordingly.
How could it work without changing your add() method to a pointer receiver?
You simply would have to return the copied struct in your add() method like this:
package main
import (
"fmt"
)
func main() {
var r R
r.b = make(map[int]int)
fmt.Println(r.add()) // outputs {[2] map[2:2]}
}
type R struct {
a []int
b map[int]int
}
func (r R) add() R {
r.a = append(r.a, 2)
r.b[2] = 2
return r
}

Resources