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))
    }
}