Search code examples
stringgopointerspass-by-value

What is the difference in time complexity when passing a string versus a pointer to the string as parameter to a function?


Let us say I have a string s.

 s := "helloworld"

Now, my question is, if s has 'n' bytes, what is the time complexity with respect to 'n' if I pass s to a function versus if I pass &s to a function and then access the ith byte of the string.

If it takes O(1) time when I pass &s to a function and access the ith byte of the string, then will it take O(n) time when I pass s to a function and then access the ith byte of the string (because the whole string will be copied)?

I tried this and found that copying a string does indeed change the pointer to it. Would appreciate more clarity on this.

func main() {
    str := "helloworld"
    fmt.Println("string pointer 1:", &str)
    printStringPointer(str)
}

func printStringPointer(s string) {
    fmt.Println("string pointer 2:", &s)
}

Output:

string pointer 1: 0xc000010200
string pointer 2: 0xc000010210

Solution

  • Strings in go are similar to slices, they are just a thin descriptor containing a pointer to the underlying data and a length.

    You can see this in the reflect.StringHeader type:

    type StringHeader struct {
        Data uintptr
        Len  int
    }
    

    When passing a string to a function, the header is copied, but the underlying data is not. We can change your example to print the value of Data, showing that it points to the same address in memory: playground link:

    func main() {
        str := "helloworld"
        fmt.Println("string pointer 1: ", &str)
        fmt.Println("string Data 1:    ", (*reflect.StringHeader)(unsafe.Pointer(&str)).Data)
        printStringPointer(str)
    }
    
    func printStringPointer(s string) {
        fmt.Println("string pointer 2: ", &s)
        fmt.Println("string Data 2:    ", (*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
    }
    

    Output:

    string pointer 1:  0xc000010200
    string Data 1:     4970654
    string pointer 2:  0xc000010210
    string Data 2:     4970654
    

    Passing a string is constant time (copying the header), the underlying data is not copied.