V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
shinonome
V2EX  ›  Go 编程语言

go 返回错误的时候, 返回的值应该可用吗

  •  
  •   shinonome · 17 天前 · 2463 次点击

    现在写的一个函数, 会返回多种错误, 我想的是在一些错误的时候, 值也是部份可用的, 在另一些错误的时候, 值是不可用的

    之前看到有说函数返回错误的时候, 应该默认正常返回的值为 nil, 不知道有没有这个说法

    31 条回复    2025-11-20 01:18:12 +08:00
    deplives
        1
    deplives  
       17 天前   ❤️ 1
    返回的值可用那叫错误吗?
    YanSeven
        2
    YanSeven  
       17 天前
    这会造成混乱吧。

    另外,为什么会出现错误的时候,“值是部分可用”?是函数返回多个值,然后某几个可用吗。
    那这种情况是不是一个函数揉了太多的东西了,有必要放在一个函数里面返回一堆值吗,把功能拆出来,拆成几个小函数不可以吗。
    kneo
        3
    kneo  
       17 天前 via Android
    可以,但是你需要文档写清楚,并且考虑返回值类型而不是指针。
    aladdinding
        4
    aladdinding  
       17 天前
    没有硬性规定
    unused
        5
    unused  
       17 天前
    只是一种约定,反例: https://pkg.go.dev/io#Reader
    shinonome
        6
    shinonome  
    OP
       17 天前
    @deplives #1 部份可用嘛, 一个结构体从一个网页去解析数据(网站数据更新不及时), 拿到了部份可用数据, 可以勉强进行下一步了, 但是也要分辨下进行处理
    xdeng
        7
    xdeng  
       17 天前
    // Write writes len(b) bytes from b to the File.
    // It returns the number of bytes written and an error, if any.
    // Write returns a non-nil error when n != len(b).
    func (f *File) Write(b []byte) (n int, err error) {
    shinonome
        8
    shinonome  
    OP
       17 天前
    @kneo #3 感谢回答
    shinonome
        9
    shinonome  
    OP
       17 天前
    @YanSeven #2 是一个流程的一个部份, 那个部份的解析能有一些数据, 但会因为时间太早了, 解析不对, 但也有一些可用的数据, 所以想着也返回个错误好让上面知道不是网页不对或网络引起的
    guanzhangzhang
        10
    guanzhangzhang  
       17 天前
    你可以实现两个接口,一个是 Error 接口,另一个是你定义的接口
    PTLin
        11
    PTLin  
       17 天前
    你需要的是把数据包装到错误中。
    ```go
    type MyErr struct {
    value int
    }

    func (err *MyErr) Error() string {
    return "MyErr"
    }

    func test(a int) (int, error) {
    if a%2 == 0 {
    return a, nil
    }
    return 0, &MyErr{value: a}

    }
    func main() {
    _, err := test(1)
    if err != nil && err.Error() =="MyErr"{
    fmt.Printf("error %d\n",err.(*MyErr).value);
    }
    }
    ```
    shinonome
        12
    shinonome  
    OP
       17 天前
    @PTLin #11 对哦, 是这样的
    gongym
        13
    gongym  
       17 天前
    看起来是很正常的需求,没必要自定义 error

    在一个有很多步骤的逻辑中,虽然中间某一步骤报错,但是仍然根据返回的可用值继续进行,这个操作没啥毛病

    go 语言挺自由的,没有那么多严格规范
    simon8410
        14
    simon8410  
       17 天前
    从程序流程角度看,发生错误之后,程序会进入错误处理流程,即使部分结果可用意义也不大了,除非你在错误处理流程中做正常的业务逻辑处理,一般不会这么做,也不推荐。
    kuanat
        15
    kuanat  
       17 天前
    参考官方的设计意图:

    https://go.dev/blog/errors-are-values
    https://go.dev/blog/go1.13-errors

    我补充一点个人理解:

    Golang 语境中的错误 error 是一种可以预期的行为,预期之外的叫 Panic (对应其他编程语言中的 Exception )。

    基于这种思想,Golang 中的错误处理有两个特点:

    第一个特点就是上面两篇官方文档提到的,错误是值,使用这个值的方式是 wrap/unwrap ;

    第二个特点是 Golang 主张显式控制流,所有的错误都应该按照调用链传播,并在恰当的位置进行处理。

    这里“处理”的含义是停止传播,即忽略也是一种处理方式。
    gongym
        16
    gongym  
       17 天前
    另外就算是报错,也不能简单的定义为流程无法进行

    比如有些程序某些接口很容易因为各种原因无法获取到最新的值,选择重试几次,或者忽略此时的错误就可以了。是不会影响其他接口的获取和整体的刷新逻辑的
    PTLin
        17
    PTLin  
       17 天前
    @shinonome 而且这种错误里包值的做法是非常场景的,为此 go 还内置了 errors 包替代这种手动转型和判断。
    InDom
        18
    InDom  
       17 天前
    您输入的密码部分有误(第 1 、3 、4 、6 位错误).

    错误了, 就不应该在给出部分正确的信息, 除非这个错误本身就是可接受的, 比如同时向 100 个 API 推送消息, 但有个别 API 失败了这种场景(不影响主流程的).

    大家有共识, 也不算问题.
    looplj
        19
    looplj  
       17 天前
    那就别返回错误,因为看起来你的这个场景不是错误,部分失败是一个正常的业务流程。

    返回一个 Result 之类的结构,里面定义状态, 成功,失败,部分失败之类的。
    eudore
        20
    eudore  
       17 天前
    标准库有示例, 返回值和 error 同时不为空。
    paceewang1
        21
    paceewang1  
       17 天前
    返回 err 了,一般值就认为是失效了,特别是有指针的情况下,但是没有硬性规定,只是一个代码风格问题吧。
    但是说实话,没想到有什么情况下是返回了 err ,返回值还部分可用的,这种情况一定是函数里面做了两个步骤,然后其中一个步骤的 err 是可以忽略的,那为什么不拆成两个函数呢。
    xg62718
        22
    xg62718  
       16 天前
    不可用!
    deplives
        23
    deplives  
       16 天前
    @shinonome #6 那这个不叫错误啊
    THESDZ
        24
    THESDZ  
       16 天前
    // 声明类型方便理解
    var err error
    var warnings []warning
    var result xxx
    // 调用
    err,warnings,result = callfunc(args)
    可以参考这种。
    dobelee
        25
    dobelee  
       16 天前 via iPhone
    你敢用的话可以。
    lysShub
        26
    lysShub  
       16 天前
    我也问过 https://www.v2ex.com/t/1132824 ,这种情况主要存在于 Read 、Write ,其实没什么用;

    自己写的函数还是不要搞这种了
    proxychains
        27
    proxychains  
       16 天前
    返回的 err!=nil, 那么该函数应当是不可信的, 因为它内部产生了错误.
    DefoliationM
        28
    DefoliationM  
       16 天前
    大部分情况不应该,特殊情况应写清楚注释。
    everhythm
        29
    everhythm  
       16 天前
    可以的,如果情况多的话,类似 http status code
    willchen
        30
    willchen  
       16 天前
    那就不应该用错误,你自己定一个状态码呗
    iseki
        31
    iseki  
       3 天前 via Android
    取决于你的设计,Go 对这个看上去没有强烈观点,因为标准库两种选择都有。
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   2620 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 09:37 · PVG 17:37 · LAX 01:37 · JFK 04:37
    ♥ Do have faith in what you're doing.