**今天我们说一个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())
}
}
}
}
```
有疑问加站长微信联系(非本文作者))