0

I'm confused because there seem to be two ways to initialize a pointer to a struct in the go language and they appear to me to be somewhat opposite in logic.

var b *Vertex
var c &Vertex{3 3}

Why does one use a * and the other use a & if b and c have the same resulting type? My apologies for not adequately understanding the posts already up related to this topic.

I am also not yet straight on the implications of "receivers" in this context. The terminology I am familiar with is "reference to (a)" or "pointer to (a)" or "address of (a)" and "de-reference of" or "value at address".

Thanks in advance for your help.

3 Answers 3

2

There are a number of ways to declare a pointer to a struct and assign values to the struct fields. For example,

package main

import "fmt"

type Vertex struct {
    X, Y float64
}

func main() {
    {
        var pv *Vertex
        pv = new(Vertex)
        pv.X = 4
        pv.Y = 2
        fmt.Println(pv)
    }

    {
        var pv = new(Vertex)
        pv.X = 4
        pv.Y = 2
        fmt.Println(pv)
    }

    {
        pv := new(Vertex)
        pv.X = 4
        pv.Y = 2
        fmt.Println(pv)
    }

    {
        var pv = &Vertex{4, 2}
        fmt.Println(pv)
    }

    {
        pv := &Vertex{4, 2}
        fmt.Println(pv)
    }
}

Output:

&{4 2}
&{4 2}
&{4 2}
&{4 2}
&{4 2}

References:

The Go Programming Language Specification

Variable declarations

Short variable declarations

Address operators

Allocation

Composite literals

Receivers are used for methods. For example, v is the receiver for the Vertex Move Method.

package main

import "fmt"

type Vertex struct {
    X, Y float64
}

func NewVertex(x, y float64) *Vertex {
    return &Vertex{X: x, Y: y}
}

func (v *Vertex) Move(x, y float64) {
    v.X = x
    v.Y = y
}

func main() {
    v := NewVertex(4, 2)
    fmt.Println(v)
    v.Move(42, 24)
    fmt.Println(v)
}

Output:

&{4 2}
&{42 24}

References:

The Go Programming Language Specification

Method sets

Method declarations

Calls

Method expressions

Method values

Sign up to request clarification or add additional context in comments.

Comments

1

var c = &Vertex{3, 3} (you do need the =) is declaring a struct and then getting the reference to it (it actually allocates the struct, then gets a reference (pointer) to that memory).

var b *Vertex is declaring b as a pointer to Vertex, but isn't initializing it at all. You'll have a nil pointer.

But yes, the types are the same.

You can also do:

var d *Vertex
d = &Vertex{3,3}

2 Comments

Thanks guys. What I'm gathering is that the * operator on a type isn't the de-reference operator I was assuming but more like a pointer operator to a nil instance whereas & is a pointer operator to an initialized instance. Is that right?
* does do dereference, but it's often not required, because when you call functions using a pointer, it automatically dereferences if needed. When you pass things as parameters to functions is when the type matters, and you might need to pass a reference or a pointer. When you define the type of a parameter while declaring a function, you should use * as well (if you want a pointer to be passed in), because that defines a pointer to Vertex.
0

In addition to what Wes Freeman mentioned, you also asked about receivers.

Let say you have this:

type Vertex struct {
} 

func (v *Vertex) Hello() {
   ... do something ...
}

The Vertex struct is the receiver for the func Hello(). So you can then do:

d := &Vertex{}
d.Hello()

2 Comments

Receivers do not have to be structs. For example, if we have type Integer int then we can have a receiver of type Integer or *Integer.
@peterSO Thank you for pointing that out. I modified my statement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.