Go RPC服务端和客户端的错误类型?

gorpc服务端返回的gorm.ErrRecordNotFound与客户端的gorm.ErrRecordNotFound使用errors.Is比较的结果为false

尝试在两端都注册:

gob.Register(gorm.ErrRecordNotFound)

errors.Is依旧返回false

现在的解决方案是直接比较字符串的相等性来判断是不是ErrRecordNotFound错误。

想问下,如果利用errors.Is来比较的话,要怎样实现?

阅读 2.2k
2 个回答

首先从 is 方法出发,这个方法本质是比较 error 是否同源,即用于将比较包装后的 error 是否为源 error
image.png

然后从 gob 编码角度出发,下面的代码或许能简单的去测试和理解

package main

import (
    "bytes"
    "encoding/gob"
    "errors"
    "fmt"
    "log"
)

type MyError struct {
    Msg string
}

func (m MyError) Error() string {
    return m.Msg
}

func main() {
    input := []byte{29, 255, 129, 3, 1, 1, 7, 77, 121, 69, 114, 114, 111, 114, 1, 255, 130, 0, 1, 1, 1, 3, 77, 115, 103, 1, 12, 0, 0, 0, 8, 255, 130, 1, 3, 116, 116, 116, 0}
    buf := bytes.NewBuffer(input)
    dec := gob.NewDecoder(buf)

    m := MyError{}

    if err := dec.Decode(&m); err != nil {
        log.Fatal(err)
    }

    fmt.Println("error msg is:", m)

    fmt.Println(errors.Is(m, MyError{}))
}

// 其实我觉得可以简单理解为如下这样,虽然有失偏颇

fmt.Println(errors.Is(errors.New("record not found"), errors.New("record not found")))

经过编码后两者应该并不同源,故应该无法相等。

个人建议:无论结果或原因如何,项目中并不建议直接比较错误类型,建议采用错误编码,code 或 msg 更稳妥,这也是 grpc 有 code status 的原因吧。

代码写错了吧。。。

func TestName(t *testing.T) {

t.Log(errors.Is(gorm.ErrRecordNotFound, gorm.ErrRecordNotFound)) //true

}

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题