I just started diving into Go recently and I have one major point of confusion: I am struggling to understand when exactly it is necessary to dereference a pointer explicitly.
For example I know that the . operator will handle dereferencing a pointer
ptr := new(SomeStruct)
ptr.Field = "foo" //Automatically dereferences
In what other scenarios does go do this? It seems to for example, with arrays.
ptr := new([5][5]int)
ptr[0][0] = 1
I have been unable to find this in the spec, the section for pointers is very short and doesn't even touch dereferencing. Any clarification of the rules for dereferencing go's pointers would be great!
The selector expression (e.g. x.f) does that:
Selectors automatically dereference pointers to structs. If x is a pointer to a struct,
x.y is shorthand for (*x).y; if the field y is also a pointer to a struct, x.y.z is
shorthand for (*(*x).y).z, and so on. If x contains an anonymous field of type *A, where
A is also a struct type, x.f is a shortcut for (*x.A).f.
The definition of the index expressions specifies that an array pointer may be indexed:
For a of pointer to array type:
a[x] is shorthand for (*a)[x]
Related
Interfaces already contain a pointer to a value, and I in my case it's a struct, and I need to get a struct pointer out of an interface{}.
The use case is with sync.Map, where I put a struct containing a lock into the map, and with the Load() method I can read an interface{} value. I want to get the pointer to the original struct, so I don't copy the lock.
The alternative is to add a pointer to the struct to the Map instead, then read it back and cast the interface{} to the struct pointer, but I'm curious if the first case can be achieved.
You can't do that. If you "wrap" a non-pointer value in an interface, you can only get a non-pointer value out of it, using either a type assertion or a type switch. And since type assertion expressions are not addressable, you can't get the address of the "value" wrapped in the interface.
If you only have a value wrapped in an interface, you won't be able to get a pointer to the original value that was wrapped in the interface. Why? Because the value wrapped in the interface may only be a copy, completely detached from the original. See examples and explanation here: How can a slice contain itself?
Note that under the hood the value actually wrapped may or may not be a pointer (depending on the value's size) even if you wrapped a non-pointer value, but this is implementation detail and is hidden from you. When you extract the value, you will of course get a non-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.
What is use of **Type in the Go language?
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
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.
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.
I have the following function:
func bytesToData(data interface{}, b []byte) error {
buf := bytes.NewBuffer(b)
dec := gob.NewDecoder(buf)
return dec.Decode(data)
}
I use this for getting struct data in and out of boltdb. What I'd like to do, is change that signature to:
func bytesToData(data *interface{}, b []byte) error
And then I'd like to be able to call it like this (b in this case is a gob-encoded Account)
acc := &Account{}
err := bytesToData(acc, b)
But when I do that, I get an error like Cannot use *Account for type *interface{}.
For now, I've just changed it back to interface{}. But then, if I pass in an Account or some other type directly without making it a pointer, gob throws an error. It seems like this should be checkable at compile time. And given that an argument of type interface{} accepts anything, why doesn't an argument of type *interface{} accept a pointer to anything?
The genericity of interface types in Go is not passed on to derived types. This applies to pointers (as you noticed), and also to slices, channels, etc. For example, you can't assign a []string to a []interface{}.
There are various ways to explain this. For a Haskell programmer:
Go does not have covariant or contravariant types. All type constructors (such as the * that creates a pointer type) are invariant. So even though Account and *Account (and all other types) are subtypes of interface{}, nothing is a subtype of *interface{} or []interface{}. This is sometimes inconvenient, but it keeps Go's type system and assignability rules much simpler.
For a C programmer:
An interface{} can hold a value of any type, but it does not hold it directly. Rather than being a variable-sized magic container, it is just a struct consisting of a pointer to a type and a pointer to a value. When you assign a concrete type to an interface{}, both of these fields are filled in. *interface{} is a pointer to one of these structs. When you try to assign a *Account to a *interface{}, there is nowhere to put the type information, because the *interface{} is a single machine word that just holds a pointer. So the compiler won't let you do that.
interface{} could also contain a pointer with no problem.
But there is nothing like a pointer to interface{}
See these:
Cast a struct pointer to interface pointer in Golang
Why can't I assign a *Struct to an *Interface?
I'm trying to understand Rust pointer types and their relation to mutability. Specifically, the ways of declaring a variable which holds the pointer and is itself mutable -- i.e. can be pointed to some other memory, and declaring that the data itself is mutable -- i.e. can be changed through the value of the pointer variable.
This is how I understand plain references work:
let mut a = &5; // a is a mutable pointer to immutable data
let b = &mut 5; // b is an immutable pointer to mutable data
So a can be changed to point to something else, while b can't. However, the data to which b points to can be changed through b, while it can't through a. Do I understand this correctly?
For the second part of the question -- why does Box::new seem to behave differently? This is my current understanding:
let mut a = Box::new(5); // a is a mutable pointer to mutable data
let c = Box::new(7); // c is an immutable pointer to immutable data
new should return a pointer to some heap-allocated data, but the data it points to seems to inherit mutability from the variable which holds the pointer, unlike in the example with references where these two states of mutability are independent! Is that how Box::new is supposed to work? If so, how can I create a pointer value to mutable data on the heap that is stored in an immutable variable?
First, you do understand how references behave correctly. mut a is a mutable variable (or, more correctly, a mutable binding), while &mut 5 is a mutable reference pointing to a mutable piece of data (which is implicitly allocated on the stack for you).
Second, Box behaves differently from references because it is fundamentally different from references. Another name for Box is owning/owned pointer. Each Box owns the data it holds, and it does so uniquely, therefore mutability of this data is inherited from mutability of the box itself. So yes, this is exactly how Box should work.
Another, probably more practical, way to understand it is to consider Box<T> exactly equivalent to just T, except of fixed size and allocation method. In other words, Box provides value semantics: it is moved around just like any value and its mutability depends on the binding it is stored in.
There are several ways to create a pointer to a mutable piece of data on the heap while keeping the pointer immutable. The most generic one is RefCell:
use std::cell::RefCell;
struct X { id: u32 }
let x: Box<RefCell<X>> = Box::new(RefCell::new(X { id: 0 }));
x.borrow_mut().id = 1;
Alternatively, you can use Cell (for Copy types):
let x: Box<Cell<u32>> = Box::new(Cell::new(0));
x.set(1);
Note that the above examples are using so-called "internal mutability" which should better be avoided unless you do need it for something. If you want to create a Box with mutable interior only to keep mutability properties, you really shouldn't. It isn't idiomatic and will only result in a syntactic and semantic burden.
You can find a lot of useful information here:
Ownership
References and borrowing
Mutability
std::cell - internal mutability types
In fact, if you have a question about such fundamental things as mutability, it is probably already explained in the book :)
How do I take the address of a value inside an interface?
I have an struct stored in an interface, in a list.List element:
import "container/list"
type retry struct{}
p := &el.Value.(retry)
But I get this:
cannot take the address of el.Value.(retry)
What's going on? Since the struct is stored in the interface, why can't I get a pointer to it?
To understand why this isn't possible, it is helpful to think about what an interface variable actually is. An interface value takes up two words, with the first describing the type of the contained value, and the second either (a) holding the contained value (if it fits within the word) or (b) a pointer to storage for the value (if the value does not fit within a word).
The important things to note are that (1) the contained value belongs to the interface variable, and (2) the storage for that value may be reused when a new value is assigned to the variable. Knowing that, consider the following code:
var v interface{}
v = int(42)
p := GetPointerToInterfaceValue(&v) // a pointer to an integer holding 42
v = &SomeStruct{...}
Now the storage for the integer has been reused to hold a pointer, and *p is now an integer representation of that pointer. You can see how this has the capacity to break the type system, so Go doesn't provide a way to do this (outside of using the unsafe package).
If you need a pointer to the structs you're storing in a list, then one option would be to store pointers to the structs in the list rather than struct values directly. Alternatively, you could pass *list.Element values as references to the contained structures.
A type assertion is an expression that results in two values. Taking the address in this case would be ambiguous.
p, ok := el.Value.(retry)
if ok {
// type assertion successful
// now we can take the address
q := &p
}
From the comments:
Note that this is a pointer to a copy of the value rather than a pointer to the value itself.
— James Henstridge
The solution to the problem is therefore simple; store a pointer in the interface, not a value.
Get pointer to interface value?
Is there a way, given a variable of interface type, of getting a
pointer to the value stored in the variable?
It is not possible.
Rob Pike
Interface values are not necessarily addressable. For example,
package main
import "fmt"
func main() {
var i interface{}
i = 42
// cannot take the address of i.(int)
j := &i.(int)
fmt.Println(i, j)
}
Address operators
For an operand x of type T, the address operation &x generates a
pointer of type *T to x. The operand must be addressable, that is,
either a variable, pointer indirection, or slice indexing operation;
or a field selector of an addressable struct operand; or an array
indexing operation of an addressable array. As an exception to the
addressability requirement, x may also be a composite literal.
References:
Interface types
Type assertions
Go Data Structures: Interfaces
Go Interfaces
In the first approximation: You cannot do that. Even if you could, p itself would the have to have type interface{} and would not be too helpful - you cannot directly dereference it then.
The obligatory question is: What problem are you trying to solve?
And last but not least: Interfaces define behavior not structure. Using the interface's underlying implementing type directly in general breaks the interface contract, although there might be non general legitimate cases for it. But those are already served, for a finite set of statically known types, by the type switch statement.