What is being copied when passing a string as parameter?

Issue

In Golang, everything is passed by value. If I pass an array "directly" (as opposed as passing it by pointer), then any modification made in the function will be found outside of it

func f(a []int) {
    a[0] = 10
}
func main() {
    a := []int{2,3,4}
    f(a)
    fmt.Println(a)
}

Output: [10 3 4]

This is because, to my understanding, an array constitutes (among other things) of a pointer to the underlying data array.

Unless I am mistaken (see here) strings also constitute (along with a "len" object) of a pointer (a unsafe.Pointer) to the underlying data. Hence, I was expecting the same behaviour as above but, apparently, I was wrong.

func f(s string) {
    s = "bar"
}
func main() {
    s := "foo"
    f(s)
    fmt.Println(s)
}

Output: "foo"

What is happening here with the string? Seems like the underlying data is being copied when the string is passed as argument.

Related question: When we do not wish our function to modify the string, is it still recommended to pass large strings by pointer for performance reasons?

Solution

A string has two values in it: pointer to an array, and the string length. When you pass string as an argument, those two values are copied, not the underlying array.

There is no way to modify the contents of string other than using unsafe. When you pass a *string to a function and that function modifies the string, the function simply modifies the string to point to a different array.

Answered By – Burak Serdar

Answer Checked By – Robin (GoLangFix Admin)

Leave a Reply

Your email address will not be published.