gpt4 book ai didi

go - 使用 defer 函数检查命名返回错误

转载 作者:行者123 更新时间:2023-12-02 02:03:29 29 4
gpt4 key购买 nike

嗨,我想编写一个通用函数来在函数返回错误时跟踪错误消息。所以我写了这个:

func TraceError1(err *error) {
if err != nil && *err != nil {
pc := make([]uintptr, 15)
n := runtime.Callers(2, pc)
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}
}

func TraceError2(err error) {
if err != nil {
pc := make([]uintptr, 15)
n := runtime.Callers(2, pc)
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}
}

func foo() (err error) {
defer TraceError1(&err)
defer TraceError2(err)

fmt.Println("do something")

return fmt.Errorf("haha")
}

TraceError1 有效,但 TraceError2 无效。在我的理解中, error 是一个接口(interface),所以它是一个指针/地址,为什么我需要传递它的地址?为什么TraceError2无法工作?谢谢。

最佳答案

如果发生 TraceError1,您将传递一个指向指定返回值 err 的指针。指针非 nil,但它指向的值 (err) 为 nil(在 defer 时)。但是,它尚未被评估(取消引用),因为尚未调用 TraceError1。当函数运行时(foo 返回后)并且指针被取消引用,err 的值已更新(通过 foo< 内的 return 语句)/)。

但是,在 TraceError2 的情况下,会传递一个 nil 接口(interface),即使 TraceError2 最终执行,该值也将保持为 nil。

Here is a simpler example :

package main

import "fmt"

func intByValue(i int) {
fmt.Printf("i = %d\n", i)
// ^--- `i` is an integer value
// --- whatever i was passed to the function, gets printed
}

func intByRef(i *int) {
var v int = *i // i is a pointer to an int, which gets dereferenced here
// the *address* where the actual value resides was passed
// while the address stays the same, its value can change before
// i is dereferenced, and its value stored in v.
fmt.Printf("i = %d\n", v)
}

func main() {
var i int

defer intByValue(i) // passed the *value* of i, which is 0 right now
defer intByRef(&i) // passed a *pointer* to i, which contains 0 right now

i = 100 // before intByRef could "dereference" its argument, the value that it
// contained has been updated

// intByRef gets called, dereferences the value, finds 100, prints it.
// intByValue gets called, finds 0, prints it
// result should be:
// i = 100
// i = 0
}

因此不幸的是,如果您希望能够在延迟函数使用错误之前更新错误(例如,通过返回命名返回值),则必须将指针传递给变量。

换句话说,TraceError2 根本不适合您的用例。

编辑:使用正确的术语并(可能)改进示例代码。

关于go - 使用 defer 函数检查命名返回错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68719530/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com