topskip
topskip

Reputation: 17365

String pointers

Consider the following program (http://play.golang.org/p/IbAstvudtE):

package main

import (
    "fmt"
)

func changeStringValueNotOK(dest *string, src string) {
    dest = &src
}

func changeStringValueOK(dest *string, src string) {
    *dest = src
}

func main() {

    a := "Hello"
    b := "World"

    changeStringValueNotOK(&a, b)
    fmt.Println(a) // still "Hello"

    changeStringValueOK(&a, b)
    fmt.Println(a) // now "World"
}

My goal is to call a function and change the value of string. Works fine with the second function, but not with the first.

Question: what is the meaning of *dest = src compared to dest = &src? I guess the former is "the contents of dest is now src" and the latter is "change the dest variable so that it now points to the address of src" which discards the previous value, but not the contents of a. But even if I am right, I don't understand how the *dest = src works.

I hope my question isn't too fuzzy.

Upvotes: 1

Views: 141

Answers (2)

Gustavo Niemeyer
Gustavo Niemeyer

Reputation: 23001

Just to help visualize it graphically, in your main function you have this:

  Data          Variables

|  ...  |
 -------
| Hello |<----- <a string>
 -------
| World |<----- <b string>
 -------
|  ...  |

When you provide the parameters to either of these functions, it becomes:

  Data                            Parameters

|  ...  |
 -------
| Hello |<----- <a string> <----- <dest *string>
 -------
| World |<----------------------- <src string>
 -------
|  ...  |

With that scenario, when you do *dest = src, you get:

  Data                           Parameters

|  ...  |
 -------
| Hello |    ,- <a string> <---- <dest *string>
 -------    |
| World |<--/      
|       |<---------------------- <src string>
 -------
|  ...  |

Note that this effectively changes a itself, so when you return to the prior scope, you'll observe the change.

On the other hand, if you do dest = &src, you'd instead get:

  Data                           Parameters

|  ...  |
 -------
| Hello |                        <dest *string> ----,
 -------                                            |
| World |<---------------------- <src string>  <---/
 -------
|  ...  |

Which doesn't solve your problem, because both dest and src are local to the functions they're in.

As a side note, this kind of parameter passing is a common C idiom, but in Go you'd generally change such a string by returning the new value instead.

Upvotes: 4

zzzz
zzzz

Reputation: 91369

*dest = src

is: Set the value pointed at by dest to the value in src. So it's effective.

dest = &src

is: Set the value of dest to the address of src. As dest is a formal parameter of changeStringValueNotOK the change (to the pointer only, not to the pointee) is visible only locally. As the changed value is not really used, it's total effect is a no operation.

Upvotes: 5

Related Questions