Go 推迟场地分配是竞赛条件吗?
考虑以下代码:Go 推迟场地分配是竞赛条件吗?,go,Go,考虑以下代码: type foo struct { bar string } func f() *foo { ret := &foo{"before"} defer func() { ret.bar = "after" }() return ret } func main() { fmt.Println(f()) // prints "&{after}" } 动机是必须返回一个结构,但某些字段只需要在返回之前设置(例如,函数完成时的时间戳) 推迟场地分配
type foo struct {
bar string
}
func f() *foo {
ret := &foo{"before"}
defer func() { ret.bar = "after" }()
return ret
}
func main() {
fmt.Println(f()) // prints "&{after}"
}
动机是必须返回一个结构,但某些字段只需要在返回之前设置(例如,函数完成时的时间戳)
推迟场地分配是竞赛条件吗?
它是地道的吗?
有更好的办法吗 使用
defer
语句与在从函数或例程返回前调用某个语句相比,其主要优点是defer
即使在返回前出现恐慌时也会运行该语句
因此,它通常用于清理资源(例如关闭文件或网络连接),而不是设置状态
下面的函数不会打印或返回“hello”
此代码将打印,但不会返回“hello”
回答你的问题:不,它不会导致比赛。除了上述区别之外,它相当于在
return
语句之前调用某个对象。您提到函数完成时的时间戳。在这种情况下,您可以像这样使用defer
:
package main
import (
"fmt"
"time"
)
func main() {
foo()
}
func foo() {
defer trace("foo")()
time.Sleep(1 * time.Second)
}
func trace(fn string) func() {
start := time.Now()
return func() {
layout := "15:04:05.000"
end := time.Now()
fmt.Printf("%s start at %s, end at %s, total %s", fn, start.Format(layout), end.Format(layout), end.Sub(start))
}
}
输出:
foo在23:00:00.000开始,在23:00:01.000结束,总共1s
这里没有并发,所以不能有任何比赛。@JimB谢谢。这是习惯用语还是有更好的方法?做什么?目标是什么?没有理由不能在DEBER语句中设置变量,但它是否惯用取决于您的目标。这样做肯定会降低代码的可读性和可理解性。感谢所有评论。对于那些建议关闭的人,我可以问一下问题中有什么不清楚的地方吗?我只是想问,在函数体中的每个返回ret
之前粘贴ret.bar=“after”
是否是惯用方法。
func f() string {
defer fmt.Println("ello")
panic("omg")
return "hello"
}
package main
import (
"fmt"
"time"
)
func main() {
foo()
}
func foo() {
defer trace("foo")()
time.Sleep(1 * time.Second)
}
func trace(fn string) func() {
start := time.Now()
return func() {
layout := "15:04:05.000"
end := time.Now()
fmt.Printf("%s start at %s, end at %s, total %s", fn, start.Format(layout), end.Format(layout), end.Sub(start))
}
}