1

Here is a sample of Go code which I do not really understand:

type MyClass struct {
    field1      string
    field2      string
}
...
objectinstance1 := MyClass{field1:"Hello", field2:"World"}
objectinstance2 := &MyClass{field1:"Hello", field2:"World"}

I can do exactly the same thing with objectinstance1 and objectinstance2 (method call for example) with the same syntax.

So I do not understand the role of the & operator. What I understand is that objectinstance1 contains an object whereas objectinstance2 contains a pointer.

It is for me the same thing in C than the difference between char and char*.

But in this case I should use -> instead of . (dot)?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Bob5421
  • 7,757
  • 14
  • 81
  • 175
  • See realted / possible duplicates: [Calling a method with a pointer receiver by an object instead of a pointer to it?](https://stackoverflow.com/questions/38481420/calling-a-method-with-a-pointer-receiver-by-an-object-instead-of-a-pointer-to-it/38481697#38481697); and [Pointer methods on non pointer types](https://stackoverflow.com/questions/46956290/pointer-methods-on-non-pointer-types/46956348#46956348); and [What is the method set of sync.WaitGroup?](https://stackoverflow.com/a/42480671/1705598) and [Call struct method](https://stackoverflow.com/a/42643854/1705598). – icza Nov 23 '17 at 16:30
  • As a side note: in Go, there is no notion of objects. `struct != object`, as detailed in http://spf13.com/post/is-go-object-oriented/ – Markus W Mahlberg Nov 23 '17 at 19:34

4 Answers4

3

The & operator gives you a pointer to a struct, while not using it gives you the struct value.

The biggest place this is relevant is when you pass this struct over to another function - if you pass the pointer that you made using the & operator, the other function has access to the same struct. If that function changes it, you've got the changed struct as well.

If you pass the variable that you made without the & operator, the function that you pass it to has a copy of the struct. There is nothing that that function or any other function can possibly do to change what you see in your variable.

This effectively makes the value variable safe for use across multiple go routines with no race conditions - everyone has their own copy of the struct.

If you pass the pointer made with & to other go routines, all have access to the same struct, so you really want that to be intentional and considered.

Sudhir Jonathan
  • 16,998
  • 13
  • 66
  • 90
1

Difference is not visible because it’s hidden in 2 things:

  1. Operator := which assigns value and type for a variable simultaneously. So it looks like objectinstance1 and objectinstance2 are the same. But in fact first is a MyClass instance and second is a pointer to it. It will be more palpable if use long-form operator:

    var objectinstace1 MyClass = MyClass{} var objectinstance2 *MyClass = &MyClass{}

If you omit * or & variable and type become incompatible and assignment fails.

  1. Implicit pointer indirection. Go does it automatically in statements like ptr1.Field1 to access a specific field in struct by pointer to it.

    Only on rare cases when there’s ambiguity you have to use full form:

    *ptr1.Value1

    or sometimes even:

    (*ptr1).Value1

UPDATE:

Explicit pointer usage for disambiguation:

type M map[int]int

func (m *M) Add1() {
    // this doesn't work -  invalid operation: m[1] (type *M does not support indexing)
    // m[1] = 1

    // the same - invalid operation: m[1] (type *M does not support indexing)
    // *m[1] = 1

    // this works
    (*m)[1] = 1
}

https://play.golang.org/p/JcXd_oNIAw

Eugene Lisitsky
  • 12,113
  • 5
  • 38
  • 59
0
But in this case i should use -> instead of . (dot) ?

No. Golang is not C is not Golang. In Golang there is no ->. You use dot (.) for pointers aswell. Golang is meant to be simple, there is no point in introducing another operator if the intention is clear (what else would . on a pointer mean than calling a method?)

tkausl
  • 13,686
  • 2
  • 33
  • 50
0

In go, the & operator takes the address of its argument and returns a pointer to the type of the argument.

Pointer indirection happens automatically so there is no -> operator, the dot operator handles all field (member) operations and accesses for all types, whether a pointer or a struct.

package main

import (
  "fmt"
  "reflect"
)

func main() {
  type Foo struct{ name string }
  foo1 := Foo{"Alpha"} // A plain struct instance.
  foo2 := &Foo{"Bravo"} // A pointer to a struct instance.
  fmt.Printf("foo1=%v, name=%v\n", reflect.TypeOf(foo1), foo1.name)
  fmt.Printf("foo2=%v, name=%v\n", reflect.TypeOf(foo2), foo2.name)
  // foo1=main.Foo, name=Alpha
  // foo2=*main.Foo, name=Bravo
}
maerics
  • 151,642
  • 46
  • 269
  • 291