【问题标题】:Nil pointer dereference behavior when reading from stdin从 stdin 读取时的 Nil 指针取消引用行为
【发布时间】:2021-01-26 04:14:54
【问题描述】:

这是我的围棋程序:

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)
}

它的执行以 nil 指针取消引用错误结束,如下所示:

▶ 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

为什么要分配

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

错误如上,而这个

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

成功了。

两个变量(即testBoolmyName)的初始化方式相同。

【问题讨论】:

    标签: string go pointers


    【解决方案1】:

    这一行:

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

    表示为myName 指针指向的位置分配一个值。但它并不指向任何地方,它的值是nil。您不能取消引用 nil 指针,这是您所经历的运行时恐慌。

    testBool以同样的方式初始化。

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

    这里testBool 没有被取消引用,flag.Bool() 返回一个非nil 指针,该指针分配给testBool 变量,而不是 指向的值。

    要使您的应用正常运行,myName 必须指向某个位置。你必须初始化它,例如使用内置的new() 函数:

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

    或者不使用指针,只需将myName 声明为非指针即可:

    var (
        testBool *bool
        myName   string
    )
    
    
    // ...
    myName, _ = reader.ReadString('\n')
    

    在 Go 中,您无法访问未初始化的内存。如果您没有明确地为变量提供初始值,它将获得其类型的zero valuestring 的零值是空字符串"",但你原来的myName 是一个指针,而指针的零值是nil

    查看相关问题:

    Go pointer first assignment

    【讨论】:

    • 但是如果一个变量没有显式初始化它不会得到它的默认值吗? (在这种情况下"",因为我们正在谈论一个字符串),因此它分配在内存中的某个地方,所以指针得到一个地址? (这是我最初的假设)
    • @pkaramol 他们得到零值(不是默认值)。而你的myName 是一个指针,它的零值是nil。指针不能有string 类型的值,因此空字符串不可能是myName 变量的零值。请参阅编辑后的答案。
    猜你喜欢
    • 2020-06-05
    • 2014-02-06
    • 2019-10-28
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 2013-04-21
    • 2013-09-16
    相关资源
    最近更新 更多