Passing by reference and value in Go to functions

2020-07-22 02:42发布

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.

标签: pointers go
2条回答
神经病院院长
2楼-- · 2020-07-22 03:20

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.

// *int means you *must* pass a *int (pointer to int), NOT just an int!
func someFunc(x *int) {
    *x = 2 // Whatever variable caller passed in will now be 2
    y := 7
    x = &y // has no impact on the caller because we overwrote the pointer value!
}

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 type sql.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

查看更多
Evening l夕情丶
3楼-- · 2020-07-22 03:34

The purpose of reference semantics is to allow a function to manipulate data outside its own scope. Compare:

func BrokenSwap(a int, b int) {
  a, b = b, a
}

func RealSwap(a *int, b *int) {
  *a, *b = *b, *a
}

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 call RealSwap(&x, &y), you actually exchange the values of the caller's x and y. Taking the address of the variables explicitly at the call site informs the reader that those variables may be mutated.

查看更多
登录 后发表回答