广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Go函数返回nil遇到问题避坑分析
  • 590
分享到

Go函数返回nil遇到问题避坑分析

Go函数返回nil避坑Gonil 2023-01-06 15:01:31 590人浏览 泡泡鱼
摘要

目录前言问题1问题2前言 Go语言写函数时经常返回nil,然后在函数外面判断返回值是否为空。这里有个bug,记录一下 问题1 (*Type)(nil) ≠ nil func

前言

Go语言写函数时经常返回nil,然后在函数外面判断返回值是否为空。这里有个bug,记录一下

问题1

(*Type)(nil) ≠ nil

func returnsError() error {
	var p *MyError = nil
	if bad() {
		p = ErrBad
	}
	return p // Will always return a non-nil error.
}

上面函数returnsError返回的 p 永远不会与 nil 相等。

这是为什么呢,因为 error 是一个 interface,interface 之间比较需要保证两者的 Type 和 Value 两两相等

语言内的 nil 可以理解为一个 Type 和 Value 均为空的 interface 代码里面返回的 p 虽然 Value 为空,但是 Type 是 *MyError 所以 p!=nil 。

正确写法

func returnsError() error {
	if bad() {
		return ErrBad
	}
	return nil
}

这个问题不仅仅是抛出错误的时候会出现,任何返回 interface 的场景都需要注意。

问题2

type CustomError struct {
	Metadata map[string]string
	Message string
}
func (c CustomError) Error() string {
		return c.Message
}
var (
	ErrorA = CustomError{Message:"A", Matadata: map[string]string{"Reason":""}}
	ErrorB = CustomError{Message:"B"}
)
func DoSomething() error {
	return ErrorA
}

而我们在外部接收到错误之后常常会使用 errors.Is 来判断错误类型:

err:=DoSomething()
if errors.Is(err, ErrorA) {
	// handle err
}

但是会发现上面这个判断无论如何都是 false。研究一下 errors.Is 的源码

func Is(err, target error) bool {
	if target == nil {
		return err == target
	}
	isComparable := reflect.TypeOf(target).Comparable()
	for {
		if isComparable && err == target {
			return true
		}
		if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
			return true
		}
		if err = errors.Unwrap(err); err == nil {
			return false
		}
	}
}

可以看到这是一个在 error tree 上递归的流程,真值的终结条件是 err==target ,但是前提是 target 本身得是 comparable 的

所以如果我们把一个 map 放入了 error struct,就导致这个 error 变为 incomparable,永远无法成功比较。

解决方案也很简单,就是将 Error 定义指针类型:

var (
	ErrorA = &CustomError{Message:"A", Matadata: map[string]string{"Reason":""}}
	ErrorB = &CustomError{Message:"B"}
)

指针类型比较只需要是否检查是否指向同一个对象,这样就能顺利比较了。

参考

[1]深入理解 Go Comparable Type

以上就是Go 函数返回nil遇到问题避坑分析的详细内容,更多关于Go 函数返回nil避坑的资料请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: Go函数返回nil遇到问题避坑分析

本文链接: https://www.lsjlt.com/news/176997.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作