I am a bit confused about passing by reference and value in Go.
I've seen this explained of the * in front of a type.
- in front of a type name, means that the declared variable will store an address of another variable of that type (not a value of that type).
This just doesn't make sense to me.
In Java if I was passing a Database instance into a function I would do
databaseFunction(DatabaseType db) {
// do something
}
However in the go example I have it's passed like so.
func PutTasks(db *sql.DB) echo.HandlerFunc {
}
Why do we need to have the asterisk in front of the type?
According to this cheat sheet, I found.
func PrintPerson(p *Person) ONLY receives the pointer address (reference)
I don't understand why I would only want to send a pointer address as a parameter.
First, Go technically has only pass-by-value. When passing a pointer to an object, you're passing a pointer by value, not passing an object by reference. The difference is subtle but occasionally relevant. For example, you can overwrite the pointer value which has no impact on the caller, as opposed to dereferencing it and overwriting the memory it points to.
As to your question "Why do we need to have the asterisk in front of the type?": The asterisk indicates that the value is of type pointer to
sql.DB
, rather than a value of typesql.DB
. These are not interchangeable!Why would you want to send a pointer address? So that you can share the value between the caller of a function and the function body, with changes made inside the function reflected in the caller (for example, a pointer is the only way that a "setter" method can work on an object). While Java passes objects by reference always, Go passes by value always (i.e. it creates a copy of the value in the function); if you pass something to a function, and that function modifies that value, the caller won't see those changes. If you want changes to propogate outside the function, you must pass a pointer.
See also: the Go tour section on Pointers, the Go spec section on pointers, the Go spec section on the address operators
The purpose of reference semantics is to allow a function to manipulate data outside its own scope. Compare:
When you call
BrokenSwap(x, y)
, there is no effect, because the function receives and manipulates a private copy of the data. By contrast, when you callRealSwap(&x, &y)
, you actually exchange the values of the caller'sx
andy
. Taking the address of the variables explicitly at the call site informs the reader that those variables may be mutated.