2017-10-11 58 views
1

考慮下面的代碼:是否將字段分配推遲爲競賽狀態?

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

的動機是不必返回一個結構,但一些字段需要被返回之前只設置(例如,當功能完成的時間戳)。

推遲領域分配的競爭條件? 它是慣用的嗎? 有沒有更好的方法?

+5

沒有什麼這裏Concurrent公司的,所以不能有任何種族。 – JimB

+0

@JimB謝謝。這是慣用的還是有更好的方法來做到這一點? – ale64bit

+3

做什麼?目標是什麼?沒有理由不能在延遲陳述中設置變量,但是它是否符合習慣取決於您的目標。 – Flimzy

回答

1

使用defer語句與在從函數或例程返回之前調用某些東西的主要益處是defer即使在返回之前發生恐慌時也會運行該語句。

因此它通常用於清理資源(如關閉文件或網絡連接)而不是設置狀態。

下面的功能將不打印或返回「你好」

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

此代碼將打印,但不會回到「你好」

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

要回答你的問題:沒有,它贏得不會導致比賽。除了上述區別之外,它等同於在return聲明之前調用某些內容。

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