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

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

  •  
  •   shinonome · 2 天前 · 1949 次点击

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

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

    30 条回复    2025-11-07 11:34:28 +08:00
    deplives
        1
    deplives  
       2 天前
    返回的值可用那叫错误吗?
    YanSeven
        2
    YanSeven  
       2 天前
    这会造成混乱吧。

    另外,为什么会出现错误的时候,“值是部分可用”?是函数返回多个值,然后某几个可用吗。
    那这种情况是不是一个函数揉了太多的东西了,有必要放在一个函数里面返回一堆值吗,把功能拆出来,拆成几个小函数不可以吗。
    kneo
        3
    kneo  
       2 天前 via Android
    可以,但是你需要文档写清楚,并且考虑返回值类型而不是指针。
    aladdinding
        4
    aladdinding  
       2 天前
    没有硬性规定
    unused
        5
    unused  
       2 天前
    只是一种约定,反例: https://pkg.go.dev/io#Reader
    shinonome
        6
    shinonome  
    OP
       2 天前
    @deplives #1 部份可用嘛, 一个结构体从一个网页去解析数据(网站数据更新不及时), 拿到了部份可用数据, 可以勉强进行下一步了, 但是也要分辨下进行处理
    xdeng
        7
    xdeng  
       2 天前
    // 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
       2 天前
    @kneo #3 感谢回答
    shinonome
        9
    shinonome  
    OP
       2 天前
    @YanSeven #2 是一个流程的一个部份, 那个部份的解析能有一些数据, 但会因为时间太早了, 解析不对, 但也有一些可用的数据, 所以想着也返回个错误好让上面知道不是网页不对或网络引起的
    guanzhangzhang
        10
    guanzhangzhang  
       2 天前
    你可以实现两个接口,一个是 Error 接口,另一个是你定义的接口
    PTLin
        11
    PTLin  
       2 天前
    你需要的是把数据包装到错误中。
    ```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
       2 天前
    @PTLin #11 对哦, 是这样的
    gongym
        13
    gongym  
       2 天前
    看起来是很正常的需求,没必要自定义 error

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

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

    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  
       2 天前
    另外就算是报错,也不能简单的定义为流程无法进行

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

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

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

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

    自己写的函数还是不要搞这种了
    proxychains
        27
    proxychains  
       1 天前
    返回的 err!=nil, 那么该函数应当是不可信的, 因为它内部产生了错误.
    DefoliationM
        28
    DefoliationM  
       1 天前
    大部分情况不应该,特殊情况应写清楚注释。
    everhythm
        29
    everhythm  
       1 天前
    可以的,如果情况多的话,类似 http status code
    willchen
        30
    willchen  
       1 天前
    那就不应该用错误,你自己定一个状态码呗
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   2747 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 77ms · UTC 06:55 · PVG 14:55 · LAX 22:55 · JFK 01:55
    ♥ Do have faith in what you're doing.