Nil pointer dereference behavior when reading from stdin

Viewed 229

Here is my Go program:

package main

import (
    "bufio"
    "flag"
    . "fmt"
    "os"
)

var (
    testBool *bool
    myName   *string
)

func main() {
    testBool = flag.Bool("testbool", false, "test bool flag")
    flag.Parse()
    Println(*testBool)
    funcFlags()
}

func funcFlags() {
    reader := bufio.NewReader(os.Stdin)
    Print("Enter your name: ")
    *myName, _ = reader.ReadString('\n')
    Println(myName)
}

Its execution ends up with a nil pointer dereference error as shown below:

▶ go run main.go -testbool
true
Enter you name: John
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x10acc9e]

goroutine 1 [running]:
main.funcFlags()
        /Users/pantelis/Desktop/cli_testing/main.go:25 +0x1de
main.main()
        /Users/pantelis/Desktop/cli_testing/main.go:19 +0x13b
exit status 2

Why the assignment

*myName, _ = reader.ReadString('\n')

errors out as above, while this one

testBool = flag.Bool("testbool", false, "test bool flag")

succeeds.

Both variables (i.e. testBool and myName) are initialised the same way.

1 Answers

This line:

*myName, _ = reader.ReadString('\n')

Means to assign a value to where the myName pointer points to. But it doesn't point to anywhere, its value is nil. You can't dereference a nil pointer, that's a runtime panic as you experienced.

testBool is not initialized the same way.

testBool = flag.Bool("testbool", false, "test bool flag")

Here testBool is not dereferenced, flag.Bool() returns a non-nil pointer which is assigned to the testBool variable, and not to the pointed value.

To make your app work, myName must point to somewhere. You have to initialize it, e.g. with the builtin new() function:

myName = new(string)
*myName, _ = reader.ReadString('\n')

Or don't use pointers, just declare myName to be a non-pointer:

var (
    testBool *bool
    myName   string
)


// ...
myName, _ = reader.ReadString('\n')

In Go you can't access uninitialized memory. If you don't expicitly provide an initial value for a variable, it will get the zero value of its type. Zero value of string is the empty string "", but your original myName is a pointer, and zero value for pointers is nil.

See related question:

Go pointer first assignment

Related