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

cheney2022 · 2022-10-27 17:54:09 · 2115 次点击 · 预计阅读时间 2 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2022-10-27 17:54:09 的文章,其中的信息可能已经有所发展或是发生改变。

今天我们说一个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())
            }

        }

    }
}

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2115 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传