Go struct initialization - go

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.

Related

Why does object state not change when calling methods with a pointer receiver from within a map?

Consider the following code:
package main
import (
"fmt"
)
type Person struct {
Age int
M map[string]func()
}
func New() Person {
p := Person{1, make(map[string]func())}
p.M["1"] = p.Add
return p
}
func (p *Person) Add() {
fmt.Println("Age before mutating in Add", p.Age)
p.Age += 1 // here age should become 3
fmt.Println("Age after mutating in Add", p.Age)
}
func (p *Person) Run() {
fmt.Println("Age before mutating in Run", p.Age)
p.Age += 1 // here age should be 2
p.M["1"]()
fmt.Println("Age after mutating in Run", p.Age)
}
func main() {
p := New()
fmt.Println("age before", p.Age)
p.Run()
fmt.Println("age after", p.Age)
}
This produces output
age before 1
Age before mutating in Run 1
Age before mutating in Add 1
Age after mutating in Add 2
Age after mutating in Run 2
age after 2
Here M is a map member of a struct, it stores methods of the same struct against strings.
In main we instantiate a non pointer struct value.
Then we call a method Run on that struct which is defined to have a pointer receiver. This should share a pointer to the struct with the method, which should allow the method to mutate the original struct.
Within Run we call the function Add stored within the map, via the map. But this does not mutate the struct, in fact it seems to operate on the state of the object as it was when newly created.
Any changes within Add are lost by the time Run ends, although Add is also declared with a pointer receiver.
I suspect this is because the original object was copied into the map somehow when calling p.M["1"] = p.Add?
Why does calling the method with pointer receiver not mutate the object?
Playground link https://play.golang.org/p/CRer_rT8_sj
New returns a Person and not a *Person.
When you write
p := New()
it starts with New constructing a Person pnew and adding its Add method to pnew.M. Then it returns pnew.
Then this pnew is assigned to p which is a different variable. So p.M contains now pnew's Add method. When you execute p.M["1"]() in Run pnew's Age is incremented (which is unrelated to p's age.

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.

Using reflect to update value by reference when argument is not a pointer in go

I've had difficulty learning the basics of reflect, pointers and interface in go, so here's another entry level question I can't seem to figure out.
This code does what I want it to do - I'm using reflect to add another record to a slice that's typed as an interface.
package main
import (
"reflect"
"log"
)
type Person struct {
Name string
}
func Add(slice interface{}) {
s := reflect.ValueOf(slice).Elem()
// in my actual code, p is declared via the use of reflect.New([Type])
p := Person{Name:"Sam"}
s.Set(reflect.Append(s,reflect.ValueOf(p)))
}
func main() {
p := []Person{}
Add(&p)
log.Println(p)
}
If I changed the Add and main function to this, things don't work the way I want it to.
func Add(slice interface{}) {
s := reflect.ValueOf(&slice).Elem()
p := Person{Name:"Sam"}
s.Set(reflect.Append(reflect.ValueOf(slice),reflect.ValueOf(p)))
log.Println(s)
}
func main() {
p := []Person{}
Add(p)
log.Println(p)
}
That is, the log.Println(p) at the end doesn't show a slice with the record Sam in it like the way I had hoped. So my question is whether it's possible for me to have Add() receive a slice that is not a pointer, and for me to still write some code in Add() that will produce the outcome shown in my first scenario?
A lot of my recent questions dance around this kind of subject, so it's still taking me a while to figure out how to use the reflect package effectively.
No, it's not possible to append to a slice in a function without passing in a pointer to the slice. This isn't related to reflection, but to how variables are passed in to functions. Here's the same code, modified to not use reflection:
package main
import (
"log"
)
type Person struct {
Name string
}
func AddWithPtr(slicep interface{}) {
sp := slicep.(*[]Person)
// This modifies p1 itself, since *sp IS p1
*sp = append(*sp, Person{"Sam"})
}
func Add(slice interface{}) {
// s is now a copy of p2
s := slice.([]Person)
sp := &s
// This modifies a copy of p2 (i.e. s), not p2 itself
*sp = append(*sp, Person{"Sam"})
}
func main() {
p1 := []Person{}
// This passes a reference to p1
AddWithPtr(&p1)
log.Println("Add with pointer: ", p1)
p2 := []Person{}
// This passes a copy of p2
Add(p2)
log.Println("Add without pointer:", p2)
}
(Above, when it says 'copy' of the slice, it doesn't mean the copy of the underlying data - just the slice)
When you pass in a slice, the function effectively gets a new slice that refers to the same data as the original. Appending to the slice in the function increases the length of the new slice, but doesn't change the length of the original slice that was passed in. That's why the original slice remains unchanged.

Wrapped structs referencing

I am little consfused about value type struct wrapped by pointer type struct.
Example:
package main
import (
"fmt"
)
type A struct {
id int
B
}
func (a *A) setId(val int) {
a.id = val
}
type B struct {
name string
}
func (b B) setNameViaValue(val string) {
b.name = val
}
func (b *B) setNameViaPointer(val string) {
b.name = val
}
func main() {
a := new(A)
a.setId(1)
a.setNameViaValue("valuename")
fmt.Println(a)
a.setNameViaPointer("pointername")
fmt.Println(a)
}
I would expect that referencing through pointer type A struct(which addresses concrete memory) that wraps B value type struct will set inner value no matter what kind of refence to B is used (B/*B). This is also related to type definition. Can anyone also explain what is different when I define it like this? Is there any usecase scenario?
type A struct {
id int
*B
}
Why doesn't setNameViaValue end up setting the name
If you declare a method with a value (non-pointer) receiver, then that method cannot "modify" the receiver cause it will actually receive a copy.
That's why the "name" is not set as you expected with the setNameViaValue method.
If you want to be able to set the name of B in that way, only setNameViaPointer is an option.
You can read more about the differences between method and value receivers here:
https://tour.golang.org/methods/8
Why can you actually invoke the inner struct methods on the outer struct
That's because you "embedded" the inner struct in the outer one.
When you include a struct type name without giving it a field name, then all of the "inner" struct methods and fields are "promoted" to the outer one.
That means you can call a.setNameViaValue and it will be equivalent to doing a.B.setNameViaValue.
Is there any difference if I embedded as a pointer
If you define A this way:
type A struct {
id int
*B
}
Then:
The "setNameViaValue" will still not work (that's only related to the method being defined over a value instead of a pointer receiver, it has nothing to do with how A references B).
You will need to initialize B explicitly when creating an A object, otherwise *B will end up being nil. (if you reference it as a value, it will be initialized as an empty B)
You can change what *B points to later on (if it was a value, then it will always reference the same "value")

Reassigning in pointer method receiver

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.

Resources