string needs to be pointer to set nil
nil
cannot be assigned to string because nil means that the variable doesn’t have an address that stores the actual value. If string is declared without an asterisk, an empty string is assigned instead.
var str string
fmt.Printf("[%s]\n", str) // []
fmt.Println(&str) // 0xc000014300
str = string("Hello world!")
fmt.Println(str) // Hello world!
The address is also assigned without assigning an actual string. &str
means that it passes the address of str
variable. The actual string “Hello world!” is stored in the addresses that start from 0xc000014300.
Let’s check the difference when adding an asterisk.
var strPointer *string
fmt.Println(strPointer == nil) // true
fmt.Println(strPointer) // <nil>
fmt.Println(&strPointer) // 0xc000012038
The default value of the pointer variable is nil. If the data type is a pointer, the meaning of the variable is a bit different from the normal declaration.
strPointer
: address that stores the value&strPointer
: address of the pointer*strPointer
: stored value
The value is nil. Therefore, strPointer at line 3 is nil. However, &strPointer has an address because it is the address for the pointer itself.
The image of the structure is like the following.
Let’s assign a string here.
temp := string("Hello world!")
strPointer = &temp
fmt.Println(&temp) // 0xc000014320
fmt.Println(strPointer) // 0xc000014320
fmt.Println(*strPointer) // Hello world!
The new string is assigned to temp
variable. Then set the address to the address that stores the value of strPointer
. It is no longer nil, so we can finally use the value.
By the way, if the program tries to access the value *strPointer without assigning a value, it throws an error due to a segmentation violation.
var strPointer *string
fmt.Println(*strPointer)
// panic: runtime error: invalid memory address or nil pointer dereference
// [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x498168]
Updateing a value affects to another variable
You need to be careful enough to update the value when using a pointer variable. See the example below.
var strPointer *string
temp := string("Hello world!")
strPointer = &temp
temp += "Additional text."
fmt.Println(temp) // Hello world!Additional text.
fmt.Println(*strPointer) // Hello world!Additional text.
It appends a string to temp
string but strPointer
is also updated because strPointer
has the same address as temp
.
If you define a function in the following way, the passed text is modified in the function without knowing from the caller.
func doSomething(text *string) *string {
*text += "add"
return text
}
You need to be careful when a pointer is used.
Compare string and string pointer
If you want to compare string and string pointer, you need to add an asterisk to the string pointer side.
var str string
str = string("Hello world!")
var strPointer *string
temp := string("Hello world!")
strPointer = &temp
fmt.Printf("&str == strPointer => %t\n", &str == strPointer) // &str == strPointer => false
fmt.Printf("str == *strPointer => %t\n", str == *strPointer) // str == *strPointer => true
The comparison must be done in the same type. The first comparison is for address. Of course, the two addresses are different.
However, the string itself is the same. Therefore, it returns true.
Comments