Aim: understanding the difference between *string
and string
in Golang
Attempt
func passArguments() {
username := flag.String("user", "root", "Username for this server")
flag.Parse()
fmt.Printf("Your username is %q.", *username)
fmt.Printf("Your username is %q.", username)
}
results in:
Your username is "root".Your username is %!q(*string=0xc820072200)
but when the *string is assigned to a string:
bla:=*username
fmt.Printf("Your username is %q.", bla)
it is able to print the string again:
Your username is "root".Your username is %!q(*string=0xc8200781f0).Your username is "root".
Questions
"root"
vs.
%!q(*string=0xc8200781f0)
? "root"
vs.
%!q(*string=0xc8200781f0)
?A *string
is a pointer to a string. If you're not familiar with pointers, let's just say that it's a value that holds the address of another value, instead of the value itself (it's a level of indirection).
When a *
is used in a type, it denotes a pointer to that type. *int
is a pointer to an integer. ***bool
is a pointer to a pointer to a pointer to a bool.
flag.String
returns a pointer to a string because it it can then modify the string value (after the call to flag.Parse
) and you are able to retrieve that value using the dereference operator - that is, when using *
on a variable, it dereferences it, or retrieves the value pointed to instead of the value of the variable itself (which in the case of a pointer would just be a memory address).
So to answer your specific questions:
the %q
verb in the fmt
package understands strings (and slices of bytes), not pointers, hence the apparent gibberish displayed (when a value is not of the expected type for the matching verb - here %q
- the fmt
functions display %!q
along with the actual type and value passed)
A pointer to a string is very rarely used. A string in Go is immutable (https://golang.org/ref/spec#String_types) so in cases like flag.String
where you need to return a string that will be mutated later on, you have to return a pointer to a string. But you won't see that very often in idiomatic Go.
You are not assigning a *string
(pointer to a string) to a string
. What you are doing, as I mentioned earlier, is dereferencing the *string
variable, extracting its string
value. So you are in fact assigning a string
to a string
. Try removing the *
on that line, you'll see the compiler error message. (actually, because you're using the short variable declaration notation, :=
, you won't see a compiler error, but your variable will be declared as a pointer-to-a-string. Try this instead, to better understand what's going on:
var s string
s = username
That will raise the compiler error).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With