Reassigning in pointer method receiver - go

What I understand about pointer method receiver and non-pointer method receiver is first one can be modified in the method and next one isn't.
So, following worked exactly as I expected.
type student struct {
name string
age int
}
func (s *student) update() {
s.name = "unknown"
s.age = 0
}
func main() {
s := student{"hongseok", 13}
fmt.Println(s)
s.update()
fmt.Println(s)
}
It prints hongseok/13 and unknown/0.
But, I want to replace whole s in update method at once with reassigning. So, I've just altered update method as bellow.
func (s *student) update() {
s = &student{"unknown", 0}
}
And it doesn't change s in main method and prints double hongseok/13.
func (s *student) update() {
*s = student{"unknown", 0}
}
Above change fix the problem.
I think there's no semantic difference. What am I missing?

In the first example:
func (s *student) update() {
s = &student{"unknown", 0}
}
You are assigning an entirely new "pointer value" to s, and the new *s points at a new student value. The variable s is scoped only to the method body, so there are no side effects after this returns.
In the second example
func (s *student) update() {
*s = student{"unknown", 0}
}
You are dereferencing s, and changing the value of *s to point to a new student value, or to put it differently, you are putting a new student value at the address where s points.

In this example you're changing the address that is stored in s to a different value;
func (s *student) update() {
s = &student{"unknown", 0}
}
While using a pointer is regarded as 'passing by reference' the reference itself is a value like any other that is pushed onto the call stack. When you return to main, the value of s is whatever it was in that scope. So to give something more concrete, you called main with s = 1 (calling the addresses 1 and 2 for simplicity), in the method you allocate a new student located at address 2 and you set s = 2, when you return that version of s is popped from the stack and the s in main points to 1 which is unchanged.
In this latter example;
func (s *student) update() {
*s = student{"unknown", 0}
}
You're dereferencing s and assigning a new object to that location, overwriting the existing memory. When you return the pointer in main is still pointing to the same location but you have different data at that location in memory. So in this example you're writing a new student instance to address 1 so when you return you see the new value in the calling scope.

I think, your main problem is that you don't understand well neither one of two concepts that appear in your question.
Let start with pointers. When you don't use pointers, assigning of value means create a simple copy of previous value. The new value is not bound any way with previous one. That means if you change the old value or new, it does not influence the second one. This is normal for primitive types (like ints, bool, string) and structures.
a := 1
b := a
a++ // a was changed, but value of b does not change at all
And now the pointers - it is something that points to some space into memory. For simplicity we create two pointers and both will point to same place.
package main
import (
"fmt"
)
func main() {
type student struct {
name string
age int
}
p1 := &student{"hongseok", 13} // this mean create a new student, but we want only address of student, not value
p2 := p1
(*p1).age = 15 // because p1 and p2 point to same memory (*p2).age also changed
fmt.Println("1.", p2.age) // 15
p2.age = 32 // in golang I could write (*p2).ago or p2.ago this is the same
fmt.Println("2.", p1.age) // 32
fmt.Println("3.",p1, "==", p2)
fmt.Printf("4. %p == %p\n", p1, p2)
// But now I force point p2 to new place
p2 = &student{"another student", 12}
fmt.Println("5.", p1, "!=", p2)
fmt.Printf("6. %p == %p\n", p1, p2)
p1.age = 14 // does it influce p2.age? no! Why? Because it is in different address
fmt.Println("7.", p1, "!=", p2)
// but could is somehow force that point to same address ? Of course
p2 = p1 // p2 will point to same place as p1 and old value of p2 will be freed by garbage collector
}
And don't be confused - pointer can also points named value.
a := 42 // means allocate memory for integer, and we give that memory name "a"
p := &a
*p++ // it change value of a
a = 5 // and of course this change value of *p
And now back to methods, that receiver is/is not a pointer. If receiver of method is pointer, that means you can change it value - the same way as I did few lines ago.
If method receiver is not a pointer, that means - before calling a method, it will be created a copy of struct and method will be called on that copy. You of course can change value of copy, but it does not influence original value.

Related

How to determine if the pointer passed as a function argument is being modified or a copy is being modified?

package main
import (
"fmt"
)
type Numbers struct {
x int
y int
}
func initial(number *Numbers) {
number.x = 1
number.y = 1
}
func final(number *Numbers) {
number = &Numbers{2, 2}
}
func main() {
p := Numbers{0, 0}
fmt.Println(p) //Prints {0 0}
initial(&p)
fmt.Println(p) //Prints {1 1}
final(&p)
fmt.Println(p) //Expected to print {2, 2} but prints {1, 1}
}
Why does the initial function modify the pointer, while the final function modifies a copy of the pointer?
Both initial and final's function parameters point to the memory address of p in main; initial manages to change p, while final can't.
Any explanation so as why this is the case would be greatly appreciated.
To modify the data pointed to by a pointer, you must dereference the pointer. The dereference operator is *. However, Go will implicitly insert the dereference operation in some cases for ease of use. For example, number.x = 1 is translated to (*number).x = 1.
This implicit translation may be confusing, but you should see that if it that translation didn't happen, then the expression number.x = 1 would be meaningless, since number is a pointer type and pointers don't have fields.
So in summary, the initial function has implicit pointer dereference, while final does not.
If you changed final to explicitly and correctly dereference, *number = Numbers{2, 2}, then it will also change p.
The initial function works on the passed pointer, which is pointing to the variable allocated in main. All changes are performed on the object allocated in main.
The final function receives the same pointer as an argument, however, it assigns the pointer to another Numbers instance. The object in main never changes.
There is no copying involved in either function.

Go struct initialization

How come Go can be initialized using both &Person and Person?
package main
import "fmt"
type Person struct {
name string
}
func (p Person) Who() string {
return "Person: " + p.name
}
func main() {
var p1 = &Person{"Adam"}
fmt.Println(p1.Who()) // Adam
var p2 = Person{"Ben"}
fmt.Println(p2.Who()) // Ben
}
p2 := Person{"Ben"} initializes a Person struct by assigning "Ben" to name, and assigned that to p2. p2 is of a value type Person.
p1 := &Person{"Adam"} initializes a Person struct by assigning "Adam" to name, and then assigns the address of that struct to p1. p1 is of a pointer type *Person.
Who() is a method defined for a receiver of value type Person, which means, the functionality always receives a copy of the receiving instance. This is an important factor when it comes to mutability. This also works with pointer handles, such as in your example with p2, but the receiver will continue to be a local copy of the instance, unless you change the receiver definition to (p *Person), which will provide a local copy of the pointer reference.

Pointer Receiver and Value Receiver on Interfaces in Golang

This question is not as clear as I wanted to be I will ask a better question. But I do not want to marked duplicate on that. So I have flagged my own question. If you can help it to be deleted to not confuse the community. Please do the needful. Please do not downvote me while you are at it. Sorry to be unclear
I am new to golang and just getting the hang of it.
I am learning by taking Tour of Go and then using it with my own understanding.
I was at Interfaces and started to implement with my own understanding.
Here is Go PlayGround Link
Step 1 : I made 3 types an int, a struct and an interface
package main
import (
"fmt"
)
type MyInt int
type Pair struct {
n1, n2 int
}
type twoTimeable interface {
result() (int, int)
}
Step 2 : Then I implemeted twoTimeable for pointer receivers because it changes underlying value.
func (p *Pair) result() (int, int) {
p.n1 = 2 * p.n1
p.n2 = 2 * p.n2
return p.n1, p.n2
}
func (m *MyInt) result() (int, int) {
*m = 2 * (*m)
return int(*m), 0
}
Step 3 : Then I declared and assigned MyInt, Pair and their corresponding pointers in main function. I also declared twoTimeable interface
mtemp := MyInt(2)
var m1 MyInt
var m2 *MyInt
var p1 Pair
var p2 *Pair
m1, m2, p1, p2 = MyInt(1), &mtemp, Pair{3, 4}, &Pair{5, 6}
var tt twoTimeable
fmt.Println(" Values : ", m1, *m2, p1, *p2, tt)
Step 4 : The I assigned MyInt,Pair and their pointers , called the implemented method and printed.
tt = m1
fmt.Println(tt.result())
fmt.Printf("Value of m1 %v\n", m1)
tt = m2
fmt.Println(tt.result())
fmt.Printf("Value of m2 %v\n", *m2)
tt = p1
fmt.Println(tt.result())
fmt.Printf("Value of p1 %v\n", p1)
tt = p2
fmt.Println(tt.result())
fmt.Printf("Value of p2 %v\n", *p2)
It shows error :
prog.go:41:5: cannot use m1 (type MyInt) as type twoTimeable in assignment:
MyInt does not implement twoTimeable (result method has pointer receiver)
prog.go:49:5: cannot use p1 (type Pair) as type twoTimeable in assignment:
Pair does not implement twoTimeable (result method has pointer receiver)
I also read this question, I got that m1 and p1 are not addressable, thats why it wont compile.
But method result() will just work fine if I use p1, or m1 p1/m1.result() (auto dereferencing FTW)
Now in Step 2 when I change the pointer receiver to value receiver, and change *m to m(I am aware of change in Output)
func (p Pair) result() (int, int) {
p.n1 = 2 * p.n1
p.n2 = 2 * p.n2
return p.n1, p.n2
}
func (m MyInt) result() (int, int) {
m = 2 * (m)
return int(m), 0
}
It suddenly does not show compile error. shouldn't it for m2 and p2, because now there is no implementation of result using *MyInt and *Pair
That means if interface method implementation has value receiver tt can hold both pointer and value.
But when interface method implemenation has pointer reciever it cant hold non pointers.
Q1 : Why it is fine to use pointers (tt = m2) on value receiver interface methods(p MyInt) result() , but not values (tt = m1) on pointer receiver interface method(p *MyInt) result().
Now lets revert to pointer receivers.
Is there a way that if function accept param (tt twoTimeable) i will be able to invoke tt.result() irrespective tt being a pointer to type or not, given result() is only definded with pointer receiver.
See the code below:
func doSomething(tt twoTimeable) {
temp1, temp2 := tt.result()
fmt.Print("doing something with ", temp1, temp2)
}
Since tt can be any predefined type(pointer or not a pointer), accpting param (tt *twoTimeable, if I can even do that) does not seem like a solution or do I have rely on user of function to provide pointer. If i do not have to change underlying value i.e use value receiver its not a problem as tt can hold either value or pointer to that
I always Accept answer.
Q1 : Why it is fine to use pointers on value receiver methods but not vice vers?
Because the language spec say it it fine: https://golang.org/ref/spec#Method_sets :
The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).
(A possible reason why the spec is like this: Convenience.)
For the rest of the question: I do not have the slightest idea what you are asking. The code of do Something is totally fine. You invoke result on tt which is any type implementing the result() (int, int) method. Whether this type is a pointer type or not is of no interest. You get two ints back from this method call and can do whatever you want with these ints.
(Regarding the "pointer to interface" part: Yes. It is technically possible to do ttp *twoTimetable. But you never need this. Never. (Of course this is a lie but the case you need it is so rare and delicate that you really never need this as a beginner and once you do need it you will know how to use it.) There is one thing to remember here: You never do "pointer to interface".)
Is there a way that if function accept param (tt twoTimeable) i will be able to invoke tt.result() irrespective tt being a pointer to type or not, given result() is only definded with pointer receiver.
This seems to be a major missconception here. If if tt is a variable of the interface type twoTimetable than is has a result method and this method can be called. Whytever the underlying type of the tt is does not matter at all. A interface type completely encapsulates the underlying type from being relevant. An interface type provides a set of methods and these can be called and no other method can be called.
The question of assignability of a concrete type (e.g. you MyInt) to a variable of type twoInterfaces is a different question. If your concrete type (e.g. MyInt) happens to have all methods defined by the interface type (here twoTimetables) then it is assignable, if not, then not.
The question "what methods does my concrete type have" is a third question. This one is the only question which is a bit complicated. Any method defined on receiver T is a method of T. For pointer types *T the methods on *T and the methods on T count.
Shouldn't it for m2 and p2, because now there is no implementation of result using *MyInt and *Pair
No. You are conflating different things and misinterpreting the results.
Go lets you omit pointer dereferencing in most situations.
type Pair struct {
n1, n2 int
}
var pp *Pair = ...
fmt.Println(pp.n1)
See the last line? pp is a pointer to Pair but there is no need to write (*pp).n1.
This dereferencing is inserted automatically (it is the automatic variant of the -> operator in C).
Your m2 and p2 are just variables containing a pointer. If needed these pointers will be dereferenced. This has nothing to do with pointer/value-receivers or interfaces.

GoRoutines and passing struct to original context

I have a configuration that defines a number of instances (SomeConfigItems) which have a thing() created for each of them.
That thing is a struct returned by an included package, which contains, among other things, a Price (float64) and a nested struct. The nested struct maintains a map of trades.
The problem is that I am able to loop through the thing.Streams.Trades and see all trades happening in real time from my main()'s for{} loop. I am not able to see an updated thing.Price even though it is set in the Handler on occasion.
I am having a hard time understanding how the nested structs can contain data but not Price. I feel as though I am missing something with scoping, goroutines, or possibly pointers for instantiation of new objects.
Any help would be appreciated, I will continue reading in the meantime. I've reduced the code to what seems relevant.
main.go:
package main
import thing
var Things []thing.Handler
for _, name := range SomeConfigItems {
handler := thing.New(name)
Things = append(Things, handler)
}
for {
for _, t := range Things {
log.Info("Price: ", t.Price) // This is set to 0 every iteration, but I can actively data in thing.Streams.Trades
}
}
thing.go:
package thing
import streams
type Handler struct {
Name string
Price float64
Streams streams.Streams
}
func New(name string) (h Handler, err error) {
stream, err := streams.New(strings.ToLower(name))
h = Handler{
Name: name,
Price: "0.0"
Streams: stream,
}
go h.handler()
return h, err
}
func (bot *Handler) handler() {
var currentPrice float64
for {
currentPrice = external.GetPrice(bot.Name).Price // Validated that this returns a float64
bot.Price = currentPrice // Verified that this is updated immediately after in this context.
// Unable to see Price updated from outer context.
}
}
streams.go:
package streams
type Streams struct {
Trades
}
type State struct {
Price string `json:"p"`
Quantity string `json:"q"`
}
type Trades struct {
Trades map[float64]float64
TradeMutex sync.Mutex
Updates chan State
}
func New(name string) (s Streams, err error) {
p := newTradeStream(name)
s = Streams{
Trades: p,
}
return s, err
}
func newTradeStream(name string) (ts Trades) {
ts = Trades{}
ts.Trades = make(map[float64]float64, MaxDepth)
ts.Updates = make(chan State, 500)
// ... Other watchdog code
return ts
}
Note:
I am added some debug logging in multiple locations. From within the Bot Handler, the price was printed (successfully), then updated, and then printed (successfully) again -- Showing no gap in the setting of Price from within the handler() function.
When adding the same type of debugging to the main() for{} loop, I tried setting an incrementing counter and assigning the value of thing.Price -- Printing thing.Price on each loop results in 0, even if I set the price (and validate it gets set) in the same loop, it is back to 0 on the next iteration.
This behavior is why I think that I am missing something very fundamental.
In Go, arguments are passed to functions by value -- meaning what the function gets is a copy of the value, not a reference to the variable. The same is true of the function receiver, and also the return list.
It's not the most elegant description, but for the sake of explanation, let's call this the "function wall." If the value being passed one way or the other is a pointer, the function still gets a copy, but it's a copy of a memory address, and so the pointer can be used to change the value of the variable on the other side of the wall. If it is a reference type, which uses a pointer in the implementation of the type, then again a change to the thing being pointed to can cross that wall. But otherwise the change does not cross the wall, which is one reason so many Go functions are written to return values instead of just modifying values.
Here's a runnable example:
package main
import (
"fmt"
)
type Car struct {
Color string
}
func (c Car) Change() { // c was passed by value, it's a copy
c.Color = "Red"
}
func main() {
ride := Car{"Blue"}
ride.Change()
fmt.Println(ride.Color)
}
Prints "Blue"
But two small changes:
func (c *Car) Change() { // here
c.Color = "Red"
}
func main() {
ride := &Car{"Blue"} // and here
ride.Change()
fmt.Println(ride.Color)
}
And now it prints "Red". Struct is not a reference type. So if you want modifications to a struct to cross the wall without using the return list to do it, use a pointer. Of course this only applies to values being passed via argument, return list, or receiver; and not to variables that are in scope on both sides of the wall; or to modifying the underlying value behind a reference type.
See also "Pointers Versus Values" in Effective Go, and "Go Data Structures" by Russ Cox.

Are maps passed by value or by reference in Go?

Are maps passed by value or reference in Go ?
It is always possible to define a function as following, but is this an overkill ?
func foo(dat *map[string]interface{}) {...}
Same question for return value. Should I return a pointer to the map, or return the map as value ?
The intention is of course to avoid unnecessary data copy.
In this thread you will find your answer :
Golang: Accessing a map using its reference
You don't need to use a pointer with a map.
Map types are reference types, like pointers or slices[1]
If you needed to change the Session you could use a pointer:
map[string]*Session
https://blog.golang.org/go-maps-in-action
Here are some parts from If a map isn’t a reference variable, what is it? by Dave Cheney:
A map value is a pointer to a runtime.hmap structure.
and conclusion:
Conclusion
Maps, like channels, but unlike slices, are just pointers to runtime
types. As you saw above, a map is just a pointer to a runtime.hmap
structure.
Maps have the same pointer semantics as any other pointer value in a
Go program. There is no magic save the rewriting of map syntax by the
compiler into calls to functions in runtime/hmap.go.
And an interesting bit about history/explanation of map syntax:
If maps are pointers, shouldn’t they be *map[key]value?
It’s a good question that if maps are pointer values, why does the
expression make(map[int]int) return a value with the type
map[int]int. Shouldn’t it return a *map[int]int? Ian Taylor
answered this recently in a golang-nuts thread1.
In the very early days what we call maps now were written as pointers,
so you wrote *map[int]int. We moved away from that when we realized
that no one ever wrote map without writing *map.
Arguably renaming the type from *map[int]int to map[int]int, while
confusing because the type does not look like a pointer, was less
confusing than a pointer shaped value which cannot be dereferenced.
No. Maps are reference by default.
package main
import "fmt"
func mapToAnotherFunction(m map[string]int) {
m["hello"] = 3
m["world"] = 4
m["new_word"] = 5
}
// func mapToAnotherFunctionAsRef(m *map[string]int) {
// m["hello"] = 30
// m["world"] = 40
// m["2ndFunction"] = 5
// }
func main() {
m := make(map[string]int)
m["hello"] = 1
m["world"] = 2
// Initial State
for key, val := range m {
fmt.Println(key, "=>", val)
}
fmt.Println("-----------------------")
mapToAnotherFunction(m)
// After Passing to the function as a pointer
for key, val := range m {
fmt.Println(key, "=>", val)
}
// Try Un Commenting This Line
fmt.Println("-----------------------")
// mapToAnotherFunctionAsRef(&m)
// // After Passing to the function as a pointer
// for key, val := range m {
// fmt.Println(key, "=>", val)
// }
// Outputs
// hello => 1
// world => 2
// -----------------------
// hello => 3
// world => 4
// new_word => 5
// -----------------------
}
From Golang Blog-
Map types are reference types, like pointers or slices, and so the value of m above is nil; it doesn't point to an initialized map. A nil map behaves like an empty map when reading, but attempts to write to a nil map will cause a runtime panic; don't do that. To initialize a map, use the built in make function:
// Ex of make function
m = make(map[string]int)
Code Snippet Link Play with it.

Resources