在Go中,当一个函数返回一个错误时,其他变量是否总是它的";“零”;价值

在Go中,当一个函数返回一个错误时,其他变量是否总是它的";“零”;价值,go,Go,我说的是Go标准库: output, err := abc.Xyz() if err != nil { // by convention is `output` always its "zero" value? } 不总是这样。例如,io.Reader: Reader是封装基本读取方法的接口 Read最多可将len(p)字节读入p。它返回字节数 已读(0个字节之前返回) 考虑错误错误。这样做可以正确地处理 在读取一些字节以及两个允许的EOF后发生 行为 不鼓励Read的实现返回零字

我说的是Go标准库:

output, err := abc.Xyz()
if err != nil {
    // by convention is `output` always its "zero" value?
}

不总是这样。例如,
io.Reader

Reader是封装基本读取方法的接口

Read最多可将len(p)字节读入p。它返回字节数 已读(0个字节之前返回) 考虑错误错误。这样做可以正确地处理 在读取一些字节以及两个允许的EOF后发生 行为

不鼓励Read的实现返回零字节 计数时出现零错误,len(p)==0时除外。调用方应处理 返回0和零,表示没有发生任何事情;在 特别是,它不表示EOF

实现不能保留p

比如说,

readfile.go

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
)

func main() {
    f, err := os.Open("readfile.go")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer f.Close()
    r := bufio.NewReader(f)

    fileLen := int64(0)
    buf := make([]byte, 0, 4*1024)
    for {
        n, err := r.Read(buf[:cap(buf)])
        buf = buf[:n]
        if n == 0 {
            if err == nil {
                continue
            }
            if err == io.EOF {
                break
            }
            fmt.Println(err)
            return
        }

        // Do something with buf
        fileLen += int64(len(buf))

        if err != nil && err != io.EOF {
            fmt.Println(err)
            return
        }
    }
    fmt.Println("file length:", fileLen, "bytes")
}

如果
err!=nil
,则除非文档另有说明,否则假定所有其他值都未定义。

按照惯例,但Go不作为规则强制执行。在标准库中,我想不出任何东西(从头开始)但是,这并不符合此经验法则。如果函数希望检查err,它通常甚至不会定义其他值。函数的定义需要足够具体才能知道这一点。在某些情况下,非nil err可能会让您转到主返回值以查找错误消息等提示。
package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
)

func main() {
    f, err := os.Open("readfile.go")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer f.Close()
    r := bufio.NewReader(f)

    fileLen := int64(0)
    buf := make([]byte, 0, 4*1024)
    for {
        n, err := r.Read(buf[:cap(buf)])
        buf = buf[:n]
        if n == 0 {
            if err == nil {
                continue
            }
            if err == io.EOF {
                break
            }
            fmt.Println(err)
            return
        }

        // Do something with buf
        fileLen += int64(len(buf))

        if err != nil && err != io.EOF {
            fmt.Println(err)
            return
        }
    }
    fmt.Println("file length:", fileLen, "bytes")
}