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

cheney2022 · · 653 次点击 · · 开始浏览    

**今天我们说一个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

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