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