Why struct I pass does not change - function

I am passing a struct to a function by reference.
I was expecting if I define and change the struct inside the function I can get the new value outside.
But it is not happening.
Can anyone explain why?
package main
import "fmt"
func intbyRef(i *int) {
*i = 10
}
type ttt struct {
a int
}
func change(t *ttt) {
var p ttt = ttt{7}
fmt.Println(p)
t = &p
}
func main() {
i := 1
var t *ttt
fmt.Println(i)
fmt.Println(t)
change(t)
intbyRef(&i)
fmt.Println(i)
fmt.Println(t)
}
You can try the code in here: https://play.golang.org/p/I-GIdIZ9c6

You are not changing the struct inside the function, you are changing the value by setting it to a different memory address. In other words, you're not changing the object stored at the address referenced by t, you're changing the pointer value of t itself, which will not change the pointer value of the t variable outside the function (because Golang is pass by value).
In order to do what you want, the code should look similar to what you're doing for intbyRef, namely:
func change(t *ttt) {
var p ttt = ttt{7}
fmt.Println(p)
*t = p
}
however, this will panic with a nil-pointer dereference. Your main function should also do what you're doing with the int:
func main() {
i := 1
// var t *ttt
t := new(ttt)
...
}
Full code below (playground link here):
package main
import "fmt"
func intbyRef(i *int) {
*i = 10
}
type ttt struct {
a int
}
func change(t *ttt) {
var p ttt = ttt{7}
fmt.Println(p)
// t = &p
*t = p
}
func main() {
i := 1
// var t *ttt
t := new(ttt)
fmt.Println(i)
fmt.Println(t)
change(t)
intbyRef(&i)
fmt.Println(i)
fmt.Println(t)
}
Also, you may want to be guarding against nil values and returning errors, especially for functions internal to your package.

In our code, you are creating new object of ttt in function change and assigning it to t which is passed as parameter to function. In go parameters are passed by value, so when at the end of function change you assign value to t is only for the scope of the function. In order to propagate change to calling function return value from change and assign it back.
Have made the changes to your code, please check play ground link
https://play.golang.org/p/S3GK0JLDHn

You are passing initialized pointer value to intByRef and change the dereferenced value.
In the change you are passing not initialized pointer value (aka nil) and assigning another pointer to it.
So you are doing two different things.
You should know that when you pass a pointer to a function you pass a copy of that pointer (pointing to the same value). That's why main's t is unchanged after passing it to change. It points to the "old" memory address.
If you want to change a value of ttt pointer passed to the function you can do it like you do it in intByRef, but the pointer must be initialized (aka. allocated). Otherwise you'd try to dereference nil.
playground
func change(t *ttt) {
var p ttt = ttt{7}
fmt.Println(p)
*t = p
}
func main() {
t := new(ttt)
fmt.Println(t)
change(t)
fmt.Println(t)
}

Related

Reassigning a pointer func parameter

I'm trying to reassign a pointer to a new value that's been passed on as func parameter, but once I step out of the function, the pointer has a nil value again.
I've stepped through the code and it seems to work until I step out of the function into the calling function where the passed on pointer still holds a NIL value.
func Prepare(db *sqlx.DB, stmt *sqlx.Stmt, query String) error {
res,err := db.PreparexStatement(context.Background(), query)
stmt = res
return err
}
I would expect the following to work:
func Boot(db *sqlx.DB, stmt *sqlx.Stmt, query String) {
err := Prepare(db, stmt, query)
if err != nil {
//handle
}
}
I'm still fairly new to GO, so I believe I fail to grasp a concept here. Any help would be greatly appreciated.
Parameters act as local variables inside a function. You may change their values, but that only changes the values of the local variables. They are independent from the variables whose value you pass.
If you want to modify something, you have to pass its address, and modify the pointed value, e.g.:
func main() {
var x int
fmt.Println("before", x)
set(&x)
fmt.Println("after", x)
}
func set(i *int) {
*i = 2
}
Outputs (try it on the Go Playground):
before 0
after 2
The same thing applies to pointer variables: if you want to modify a pointer variable, you again have to pass its address, and modify the pointed value. In case of a pointer, the type will be a pointer to pointer, e.g.:
func main() {
var x *int
x = new(int)
fmt.Println("before", x, *x)
set(&x)
fmt.Println("after", x, *x)
}
func set(i **int) {
p := new(int)
*p = 2
*i = p
}
Output (try it on the Go Playground):
before 0x416020 0
after 0x416040 2
Of course if you have a pointer variable and don't want to modify the pointer value just the pointed value, you can just pass the pointer, and modify the pointed value:
func main() {
var x *int
x = new(int)
fmt.Println("before", x, *x)
set(x)
fmt.Println("after", x, *x)
}
func set(i *int) {
*i = 2
}
Output (try it on the Go Playground):
before 0x416020 0
after 0x416020 2
One thing to note: you can't pass a nil pointer to a function and expect to be able to assign anything to the pointed value: nil pointers point to nowhere. You have to pass a non-nil pointer, or as an alternative you may return the pointer value (and assign it at the caller).

Function is not changing the pointer after return

Language is 'Go' ('Golang').
The Function initApp is receiving a Pointer to an Object ('struct' in Go).
Inside the Function I create a new Object Pointer and initialize the Value of the Object. Printing and Debugger both show that before the Function's Return everything is good.
But after the Return, the Pointer which was the Function's Argument has the same empty Value as before the Function Call.
Why is that so?
Code is here:
https://pastebin.com/0Gww2CQC
// ptr.go.
package main
import "fmt"
type ClassX struct {
Name string
Age int
}
func main() {
var obj *ClassX
initApp(obj)
fmt.Println(obj)
return
}
func initApp(x *ClassX) {
tmp := NewClassXObject()
x = tmp
fmt.Println("tmp:", tmp)
fmt.Println("x:", x)
}
func NewClassXObject() *ClassX {
x := new(ClassX)
x.init()
return x
}
func (o *ClassX) init() {
o.Age = 123
o.Name = "John"
}
The Output is following:
tmp: &{John 123}
x: &{John 123}
<nil>
Thank You!
Remember, everything in Go is passed by value. When you pass a pointer, you're passing the pointer by value. Your function argument is a new local variable with the same value as was passed to it by the caller; i.e. a new pointer which points to the same memory location. So your code:
func initApp(x *ClassX) {
tmp := NewClassXObject()
x = tmp
fmt.Println("tmp:", tmp)
fmt.Println("x:", x)
}
Creates a new *ClassX in tmp, then overwrites x with the new pointer to a new memory location, then returns. None of that has any impact on the caller's scope; the pointer the caller passed still points to the same memory address it did before. You can change the value that x points to:
func initApp(x *ClassX) {
tmp := NewClassXObject()
*x = *tmp
fmt.Println("tmp:", tmp)
fmt.Println("x:", x)
}
Now you have two pointers to two separate memory locations, and you're copying the value that one points to into the memory the other points to, so that they both point at two identical values in two separate memory locations. This is what you would do if you wanted to overwrite the value pointed to by the caller.
However, since this creates a new value, it seems likely that what you want is not to overwrite the caller's value, but to return a new value. The uses of pointers as "output parameters" are very, very limited in Go; because you can return multiple values, you almost always just want to return the value rather than updating a pointer argument:
func initApp() *ClassX {
return NewClassXObject()
}
func main() {
var obj = initApp()
fmt.Println(obj)
}

Why Doesn't a Go Function Field Setter Retain the Function?

Given this short program:
package main
import "fmt"
type Foo struct {
doer func()
}
func (f Foo) SetDoer(doer func()) {
f.doer = doer
}
func main() {
foo := Foo{func() { fmt.Println("original") }}
foo.doer()
foo.SetDoer(func() { fmt.Println("replacement") })
foo.doer()
}
The output is:
original
original
I had expected it to be:
original
replacement
Why isn't it? Note that the output is as expected if I set foo.doer directly in main(). Just not if I use the SetDoer method.
In Go, the item on the left of the function name is the receiving type. This is the type from which a function can be called. However, receiver can be both pointers or value types. In this case, it is a value. The receiver is purely for the purpose of organization, under the covers, it is passed to the function like any other argument. You're passing by value so a copy of foo is passed into SetDoer, the value is modified, then the setter returns, the value goes out of scope and in the calling scope you're working with the original.
Try this;
// make the receiver a pointer
func (f *Foo) SetDoer(doer func()) {
f.doer = doer
}
// instantiate as pointer
foo := &Foo{func() { fmt.Println("original") }}
foo.SetDoer(func() { fmt.Println("replacement") })
// now the version of doer on foo has been updated.
playground example; https://play.golang.org/p/ZQlvKiluu3

Can't access function when passing object and catching it in a interface{}

Here's what I'm trying to do:
package products
ProductManager struct {
products []*Product
index int64
}
func NewPM() *ProductManager {
return &ProductManager{}
}
func (p *ProductManager) List() []*Product {
return p.products
}
---
var productManager = products.NewPM()
func main() {
api := Api{}
api.Attach(productManager, "/products")
}
func (api Api) Attach(rm interface{}, route string) {
// Apply typical REST actions to Mux.
// ie: Product - to /products
mux.Get(route, http.HandlerFunc(index(rm)))
}
func index(rm interface{}) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// allRecords := rm.List() - DOESN'T WORK. No method found.
result := reflect.TypeOf(rm) // Works, shows me the correct type.
method := result.Method(0).Name // Works as well! Shows me a function on the type.
w.Write([]byte(fmt.Sprintf("%v", method)))
}
}
Any idea on why I can't call the List() function on my productManager object? I can see the Type's functions and even get the right Type name in the index() handler.
Dead simple: rm is an empty interface variable, so it does not have any methods, that's exactly what interface{} means: No methods. If you know that rm's dynamic type is *ProductManager you can type assert it (but than you could pass a *ProductManager) Maybe you'll have to type switch on rm in the longer run. (BTW: using interface{} is almost always a bad idea.)

Dynamically create variables of certain type based on string in Go

Simple version
How can you create a variable of a certain type based upon the value of a string?
type ta struct { a int }
type tb struct { b float }
type tc struct { c string }
t := "tb"
v := MagicVarFunc(t) // Returns a new allocated var of type interface{}
v.(tb).b = 8.3
The true example
In my, surprisingly enough, working example below, I am dynamically creating variables based on a string. This is done by registering each struct type in a map with the string being the key and a nil-pointer of the type being the value.
Each type implements an interface with the method New() which returns a new variable of that specific type.
The example below is very close to what I wish to do, where each action has a set of JSON encoded data which will populate the corresponding struct. The way I've structured it is also because I wish to be able to create new stand alone actions that I register to the map.
I am not sure if am abusing the language now.
May anyone give me any pointers if I am completely out of my mind? Is there an obviously easier way?
package main
import (
"fmt"
"encoding/json"
)
// All I require of an action is that it may be executed
type ActionHandler interface {
Exec()
New() ActionHandler
}
// My list of actions
var mActions = make(map[string]ActionHandler)
// Action Exit (leaving the program)
type aExit struct {}
func (s *aExit) Exec() { fmt.Println("Good bye") }
func (s *aExit) New() ActionHandler { return new(aExit) }
func init() {
var a *aExit
mActions[`exit`] = a
}
// Action Say (say a message to someone)
type aSay struct {
To string
Msg string
}
func (s *aSay) Exec() { fmt.Println(`You say, "` + s.Msg + `" to ` + s.To) }
func (s *aSay) New() ActionHandler { return new(aSay) }
func init() {
var a *aSay
mActions[`say`] = a
}
func inHandler(action string, data []byte) {
a := mActions[action].New()
json.Unmarshal(data, &a)
a.Exec()
}
func main(){
inHandler(`say`, []byte(`{"to":"Sonia","msg":"Please help me!"}`))
inHandler(`exit`, []byte(`{}`))
}
You can use reflection to get the zero value of, or to allocate a new value (like new) of a type using reflection, if you can get the Type value at runtime. However, I don't think there is a way to get the Type from a string. You would need to have a value of that type to get the type itself.
I adopted your idea, of using a map. I map the string to the type itself, which you can get using reflect.TypeOf, which gets the type out of an interface value. Then I used reflect.Zero to get the zero value of that type (a convenient value that exists for every type). Then I got the value out as an interface.
package main
import "reflect"
type ta struct { a int }
type tb struct { b float64 }
type tc struct { c string }
var mActions map[string]reflect.Type = make(map[string]reflect.Type)
func init() {
var a ta
mActions[`ta`] = reflect.TypeOf(a)
var b tb
mActions[`tb`] = reflect.TypeOf(b)
var c ta
mActions[`tc`] = reflect.TypeOf(c)
}
func MagicVarFunc(action string) interface{} {
return reflect.Zero(mActions[action]).Interface()
}
func main() {
t := "tb"
v := MagicVarFunc(t) // Returns a new allocated var of type interface{}
x := v.(tb)
x.b = 8.3
}
jorelli's answer is very good. I'm just going to show a few options. Your "true example" looks essentially like command dispatch, with command parameters specified with JSON. To start with simple code that does this,
package main
import (
"encoding/json"
"fmt"
)
func inHandler(action string, data []byte) {
arg := make(map[string]interface{})
json.Unmarshal(data, &arg)
switch action {
case "say":
fmt.Printf("You say, %q to %s\n", arg["msg"], arg["to"])
case "exit":
fmt.Println("Good bye")
}
}
func main() {
inHandler(`say`, []byte(`{"to":"Sonia","msg":"Please help me!"}`))
inHandler(`exit`, []byte(`{}`))
}
Your register new commands by adding cases to the switch statement. Yeah, didn't think you'd like that. So, adding your map and init() idea,
package main
import (
"encoding/json"
"fmt"
)
type jmap map[string]interface{}
var mActions = map[string]func(jmap){}
func init() {
mActions["say"] = func(arg jmap) {
fmt.Printf("You say, %q to %s\n", arg["msg"], arg["to"])
}
}
func init() {
mActions["exit"] = func(jmap) { fmt.Println("Good bye") }
}
func inHandler(action string, data []byte) {
args := make(jmap)
json.Unmarshal(data, &args)
mActions[action](args)
}
func main() {
inHandler(`say`, []byte(`{"to":"Sonia","msg":"Please help me!"}`))
inHandler(`exit`, []byte(`{}`))
}
Now if you wanted, you could put each of those init functions in a separate source file and new commands could be registered by creating a new source file with a new init function.
The rest of the program is simplified with some assumptions that the commands have flat argument lists that the JSON will always encode as an object. This allows you to dispense with separate Go struct definitions for each command. inHandler just creates the same type of object (a map) for all commands, unmarshals into it, and passes it to the command. If you wanted to handle a little more arbitrary JSON, you could unmarshal into an empty interface, and the functions would have to do some extra work to dig out the arguments. If that was too much work and you really wanted to unmarshal directly into a struct, then you arrive near jorelli's solution of making each command function unmarshal its own JSON.
start by defining a function type that does the thing you want:
type Producer func([]byte) interface{}
make a few of them:
func FooProducer(raw []byte) interface{} {
foo := new(Foo)
... // do something to foo
return foo
}
func BarProducter(raw []byte) interface{} {
bar := new(Bar)
... // do something to bar
return bar
}
stick them in a map:
likeThis := map[string]Producer{
"foo": FooProducer,
"bar": BarProducer,
}
and then just do one of these:
myVal := likeThis[someString](raw)
but you probably want to define some interface and make your producer something more like:
type Producer func([]byte) MyAwesomeInterface
since there's probably some common stuff you want to do with those things you're decoding. You also probably want to handle the case of a bad string input, like-a-this:
f, ok := likeThis[someString]
if !ok {
// return, break, panic... something, just get the hell away from here.
}
myVal := f(raw)
The whole notion of inspecting types is kinda cumbersome in Go. It's generally less work to just add new types than it is to try to do reflection gymnastics with the type system.