当错误不是函数唯一返回值时,如何处理错误?

huangapple go评论101阅读模式
英文:

How to handle errors when they are NOT the only value returned by a function?

问题

我已经创建了一个处理错误的函数,代码如下:

func handleErr(e error) {
    if e != nil {
        log.Fatal("错误:", e)
    }
}

对于只返回一个错误的函数,你可以这样写:

handleErr(os.Chdir("Documents"))

然而,对于还返回其他值而不仅仅是错误的函数,你需要将代码分成两行,像这样:

s, e := os.Getwd()
handleErr(e)

是否有一种方法可以将上述两行代码压缩成一行?

英文:

I have created a function to handle errors that looks like this:

func handleErr(e error) {
	if e != nil {
		log.Fatal("Error:", e)
	}
}

For functions that only return an error, I can do the following:

handleErr(os.Chdir("Documents"))

However, for functions that also return other values and not only an error, I have to spread my code over two lines, like this:

s, e := os.Getwd()
handleErr(e)

Is there a way to condense the above two lines into one?

答案1

得分: 2

请注意,无法同时统一处理错误并返回动态类型的值。handleErr()只能返回interface{}类型的值,需要进一步进行类型断言才能提取出具体的类型。正如mkopriva的评论所指出的,需要使用泛型来使返回类型变为"动态"。

下面的答案只处理错误,但会丢弃其他返回值。

如果你可以修改handleErr()

handleErr()中添加一个interface{}类型的参数。任何值都可以赋值给interface{}

func handleErr(i interface{}, e error) {
    if e != nil {
        log.Fatal("Error:", e)
    }
}

让我们使用这个示例函数:

func foo(fail bool) (int, error) {
    if fail {
        return 0, errors.New("fail")
    }
    return 0, nil
}

进行测试:

handleErr(foo(false))
fmt.Println("First is OK")
handleErr(foo(true))
fmt.Println("Second is OK")

输出结果(在Go Playground上尝试):

First is OK
2009/11/10 23:00:00 Error:fail

handleErr(foo(false))是可行且有效的,因为规范:调用中指出:

> 作为特例,如果函数或方法g的返回值在数量上与另一个函数或方法f的参数一一对应,并且每个返回值都可以分别赋值给f的参数,则调用f(g(g的参数))将按顺序将g的返回值绑定到f的参数上。调用f除了调用g之外不能包含其他参数,而且g必须至少有一个返回值。如果f有一个最终的...参数,则将剩余的g的返回值分配给它。

如果你不能修改handleErr()

你可以编写一个辅助函数将两个返回值减少为一个:

func reduceTwoParams(i interface{}, err error) error {
    return err
}

你可以将其与返回两个值的任何函数一起使用,其中第二个值是error,因为所有值都可以赋值给interface{}

进行测试:

handleErr(reduceTwoParams(foo(false)))
fmt.Println("First is OK")
handleErr(reduceTwoParams(foo(true)))
fmt.Println("Second is OK")

输出结果(在Go Playground上尝试):

First is OK
2009/11/10 23:00:00 Error:fail

如果你想处理返回三个值的函数,你需要编写另一个辅助函数:

func reduceThreeParams(i, j interface{}, err error) error {
    return err
}
英文:

Please note that it's not possible to uniformly handle the error and return a dynamically typed value at the same time. handleErr() could only return a value of type interface{}, further type assertion would be needed to extract a concrete type from it. As noted by mkopriva's comment, generics is needed to make the return type "dynamic".

The below answer only handles the error, but discards the other return value(s).

If you can modify handleErr()

Add another parameter to handlerErr() of interface{} type. Any value is assignable to interface{}:

func handleErr(i interface{}, e error) {
	if e != nil {
		log.Fatal("Error:", e)
	}
}

Lets use this example function:

func foo(fail bool) (int, error) {
	if fail {
		return 0, errors.New("fail")
	}
	return 0, nil
}

Testing it:

handleErr(foo(false))
fmt.Println("First is OK")
handleErr(foo(true))
fmt.Println("Second is OK")

Output (try it on the Go Playground):

First is OK
2009/11/10 23:00:00 Error:fail

handleErr(foo(false)) is possible and is valid, because Spec: Calls:

> As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value. If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.

If you can't modify handleErr()

You can write a helper function which reduces 2 return values to one:

func reduceTwoParams(i interface{}, err error) error {
	return err
}

You may use this with any functions that return 2 values where second is error, because all values are assignable to interface{}.

Testing it:

handleErr(reduceTwoParams(foo(false)))
fmt.Println("First is OK")
handleErr(reduceTwoParams(foo(true)))
fmt.Println("Second is OK")

Output (try it on the Go Playground):

First is OK
2009/11/10 23:00:00 Error:fail

If you want to handle functions with 3 return values, you have to write another helper:

func reduceThreeParams(i, j interface{}, err error) error {
	return err
}

huangapple
  • 本文由 发表于 2021年12月11日 19:30:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/70314760.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定