推迟现场分配的竞争条件?

时间:2017-10-11 15:50:21

标签: 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}"
}

动机是必须返回一个结构但是只有一些字段需要在返回之前设置(例如,函数完成时的时间戳)。

推迟现场分配的竞争条件? 这是惯用的吗? 有没有更好的办法?

2 个答案:

答案 0 :(得分:1)

使用defer语句与从函数或例程返回之前调用某些内容的主要好处是defer即使在返回之前发生恐慌时也会运行该语句。

因此,它通常用于清理资源(例如关闭文件或网络连接)而不是设置状态。

以下功能不会打印或返回"你好"

func f() string {
        panic("omg")
        fmt.Println("hello")
        return "hello"
}

此代码将打印但不会返回" hello"

func f() string {
        defer fmt.Println("ello")
        panic("omg")
        return "hello"
}

回答你的问题:不,它不会导致比赛。除了上述差异之外,它等同于在return语句之前调用某些内容。

答案 1 :(得分:1)

您在功能完成时提及时间戳。在这种情况下,您可以像这样使用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 start at 23:00:00.000, end at 23:00:01.000, total 1s