Rudziankoŭ
Rudziankoŭ

Reputation: 11251

Go: **Type pointer

In tutorial is written:

The type *T is a pointer to a T value. The & operator generates a pointer to its operand.

I am just playing around with pointers in Go and have following:

example := 42

p:=&example
fmt.Println(reflect.TypeOf(&p)) // **int
fmt.Println(reflect.TypeOf(*p)) // int

So if I got it correctly, &p is a pointer to a pointer to an int value.

pointer memory scheme

What is use of **Type in the Go language?

Upvotes: 6

Views: 4132

Answers (3)

Adrian
Adrian

Reputation: 46562

A pointer allows you to pass around a memory address, so that multiple scopes can use the same address, and you can change the value at that address without changing the address; effectively allowing you to share memory. A pointer to a pointer allows you to pass around the address to a memory address, so that multiple scopes can use it and you can change the address pointed to by the shared reference. With a normal pointer, if you change the address of the pointer, any other copies of that pointer held elsewhere will become "disconnected" - they will no longer point to the same value.

For example, you might have two variables being operated on in separate workers, and a central reference you want to be able to switch back and forth between them. A pointer to a pointer is one way to achieve this; the central reference can be changed to point to the pointer used by any of the workers. Each worker would hold a pointer to a value which it would operate on normally, without needing to know if the central reference points to its pointer or not.

Or, as @Volker noted, the canonical example of the linked list. Here is an example in C but the pointer logic is the same in Go.

Upvotes: 2

peterSO
peterSO

Reputation: 166825

Here's a simple demonstration of the concept of a chain of pointers:

package main

import "fmt"

func main() {
    i := 42
    fmt.Printf("i: %[1]T %[1]d\n", i)
    p := &i
    fmt.Printf("p: %[1]T %[1]p\n", p)
    j := *p
    fmt.Printf("j: %[1]T %[1]d\n", j)
    q := &p
    fmt.Printf("q: %[1]T %[1]p\n", q)
    k := **q
    fmt.Printf("k: %[1]T %[1]d\n", k)
}

Playground: https://play.golang.org/p/WL2M1jp1T3

Output:

i: int 42
p: *int 0x10410020
j: int 42
q: **int 0x1040c130
k: int 42

Upvotes: 4

kostix
kostix

Reputation: 55563

Yes, you got it correctly.

As to "what use", it's the same as everywhere else: you use a pointer in these cases:

  • A variable has to be changed in some other code — typically another function, — and so you pass a pointer to the memory occupied by that variable to that function so it's able to update that memory via that address.

  • A value is too large to be passed around fast enough by copying it.

A pointer to a pointer is a bit of a pathological case for Go, but still this can be used in the first case: when you want some function to change the value of a pointer variable your code controls.

Upvotes: 2

Related Questions