6

panic: runtime error: invalid memory address or nil pointer dereference | 关于ni...

 1 year ago
source link: https://studygolang.com/articles/35926
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

panic: runtime error: invalid memory address or nil pointer dereference | 关于nil 无效的指针引用的问题

cheney2022 · 大约12小时之前 · 129 次点击 · 预计阅读时间 2 分钟 · 大约8小时之前 开始浏览    

今天我们说一个nil无效指针引用报错的问题 🐒 ,

错误抛出了 , 但是具体出错逻辑还是要具体分析一下,

涉及到的知识点涵盖了go基本的语法, 函数, 以及linux的文件知识, 超出code范围的内容不在讨论范围

下方code是一段通过切片完成输入缓冲的文件I/O函数

但是当你做出一些I ->O之间的额外修改可能会崩掉, 也许你可能换一种写法, 但是学习嘛, 不寒碜

func SliceRead(f *os.File) {
    // 缓冲区大小
    const BUF_SIZE = 512

    var buf [BUF_SIZE]byte

    for {
        // 这里有一个写法(非语法), 当switch的条件表达式省略(赋值语句不算), switch语句以无条件形式运行
        // buf[:] 创建了一个buf数组的完整切片
        switch nr, err := f.Read(buf[:]); true {
        case nr < 0:
            fmt.Fprintf(os.Stderr, "读取错误 %s\n", err.Error())
            os.Exit(1)
        case nr == 0:
            return
        case nr > 0:

            // 逐字打印输入的参数到标准输出
            // byte转string->byte
            str_value := []byte("标准输出 -- " + string(buf[0:nr]))

            // fmt.Fprintf(os.Stdout, "%s\n", string(str_value))
            nw, ew := os.Stdout.Write(str_value)
            if ew != nil {
                fmt.Println("写入输出出错")
            }
            fmt.Println(nw)

            // 此处会有空指针引用错误: 无效的内存地址/零指针取消引用
            // 分析: 此时nr为os.File read返回文件读取到的字节数
            // nw是 os File write 返回文件写入的字节数
            if nw != nr {
                // 此处因为我们改变了写入输出的字节数(拼接了其他字符进来, 导致字节数其实增大了) 所以一定会触发

                /**
                 * 此处Fprintf函数 将第二,第三参数格式化后写入标准错误并输出, Fprintf的第一参是一个实现了io.Writer接口的变量 返回值必须为非nil类型的错误(https://studygolang.com/static/pkgdoc/pkg/io.htm#Writer),
                 * 此时逻辑上出现了问题:
                 * 当nw!=nr时 并不一定是文件读写出错了, 因为读和写的过程中会有很多中间操作, 例如我们对最终要写出的内容的修改,
                 * 所以此时其实是正常写入输出的, ew的值为nil ,
                 * nil在go中是一个零值, nil是预定义的标识符,代表指针pointer, 通道channel, 函数func, 接口interface,映射map, 或者切片slice的零值
                 * 所以此时我们的动作变为 即将向标准错误中输出一个零值 所以在Fprintf
                 */
                fmt.Fprintf(os.Stderr, "写入错误: %s\n", ew.Error())
            }

        }

    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK