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

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

            }

        }

    }

}
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!