Golang中多个defer的使用哪种方式更好
Golang中多个defer的使用哪种方式更好
defer func(){
A()
B()
}()
或者
defer B()
defer A()
对于可写的文件,你可以使用 defer 来关闭,但务必记得最后调用 Flush() 并检查返回的错误。
更多关于Golang中多个defer的使用哪种方式更好的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我倾向于在获取资源后尽快使用单个 defer 来释放资源。
我从不使用与资源无关的 defer。
因此从我的角度来看,版本1的情况不太可能发生。
我认为使用多个 defer() 函数调用会更好。这样你就有空间在 defer func2() 中处理来自 defer func1() 的失败。
在以下代码中:
defer func(){
A()
B()
}()
你需要处理 A() 和 B() 中的任何错误。
下面的代码具有更大的灵活性,更易于处理且代码可读性更强:
defer B()
defer A()
是的,我本不该提起这件事,而且我刚刚打出来的那个例子确实不好……当然,在可写文件上使用 defer close 是可行的。但同样地,错误处理通常应该做得更好。如果你正在写入文件,但在某个地方失败了,关闭文件并不是首要考虑的问题。我们应该留下一个只写了一半的文件吗?很可能应该以某种方式清理它。如果我们做得正确,我们可能正在写入一个临时文件,打算将其重命名为最终的目标文件名。如果是这样,关闭文件并不是最后要做的事情(重命名才是),我们不应该使用 defer 来关闭它,等等。
就像我说的,这个例子不好,实际情况要复杂得多。 
我认为这取决于在上下文中哪种方式更清晰。如果它们是两个独立的事物,分开处理可能更好。
in, err := os.Open(...)
// ...
defer in.Close()
out, err := os.Create(...)
// ...
defer out.Close() // 通常不要在可写文件上延迟关闭。此处仅为示例。
如果只是两个应该一起执行的操作,放在一起也可以。例如,这里设置写入截止时间只是为了确保关闭操作能正常执行:
conn, err := net.DialTLS(...)
// ...
defer func() {
conn.SetWriteDeadline(time.Now().Add(time.Second))
conn.Close()
}()
但正如下面提到的(我进行了快速编辑,抱歉:)),这实际上是因为延迟调用仍然针对的是同一个资源。
在Go语言中,多个defer语句的执行顺序是后进先出(LIFO),因此两种方式在行为上有明显差异。第一种方式使用单个defer调用一个匿名函数,其中A()和B()按代码顺序执行;第二种方式使用两个独立的defer语句,B()会先于A()执行。
如果希望A()和B()按声明顺序执行(即先A()后B()),第一种方式更合适,因为它将多个操作封装在一个延迟函数中,确保执行顺序与代码顺序一致。第二种方式会导致逆序执行,即B()先执行,A()后执行。
示例代码说明:
package main
import "fmt"
func A() {
fmt.Println("Function A")
}
func B() {
fmt.Println("Function B")
}
func main() {
// 方式1: 使用单个defer,A()和B()按顺序执行
defer func() {
A()
B()
}()
fmt.Println("Main function - way 1")
// 输出:
// Main function - way 1
// Function A
// Function B
// 方式2: 使用多个defer,B()先执行,A()后执行
defer B()
defer A()
fmt.Println("Main function - way 2")
// 输出:
// Main function - way 2
// Function A
// Function B
}
在实际应用中,选择哪种方式取决于需求:如果多个操作需要作为一个整体按顺序延迟执行,使用第一种方式;如果需要独立控制每个延迟操作的执行顺序,使用第二种方式。第一种方式更易于维护顺序逻辑,而第二种方式在需要逆序清理资源时(如关闭文件句柄)更常见。

