要理解延遲,您需要了解替代方法。
在複雜的代碼處理許多資源,你最終會做這樣的(僞代碼)的東西:
mtx.Lock()
file1, err := os.Open(...)
if err != nil {
mtx.Unlock()
return err
}
conn, err := net.Dial(...)
if err != nil {
file1.Close()
mtx.Unlock()
return err
}
file2, err := os.Open(...)
if err != nil {
conn.Close()
file1.Close()
mtx.Unlock()
return err
}
do_things()
file2.Close()
conn.Close()
file1.Close()
mtx.Unlock()
return nil
這得到詳細的快。而且,從長期來看,它很容易出錯,因爲有人編輯代碼,並可能在打開file1之前將網絡連接的開放移動到可能無法正確更新所有錯誤處理路徑。
在C,這裏常見的成語是收集資源的全部清理在函數的末尾,做這樣的事情:
ret = ERROR;
lock(mtx);
fd1 = open(...);
if (fd1 == -1)
goto err1;
conn = net_conn(...);
if (conn == -1)
goto err2;
fd2 = open(...);
if (fd2 == -1)
goto err3;
do_things();
ret = 0;
close(fd2);
err3:
close(conn);
err2:
close(fd1);
err1:
unlock(mtx);
return ret;
這是不漂亮或者,它是很容易得到這個也是錯的。
作爲比較做同樣的事情有延遲,我們得到:
mtx.Lock()
defer mtx.Unlock()
file1, err := os.Open(...)
if err != nil {
return err
}
defer file1.Close()
conn, err := net.Dial(...)
if err != nil {
return err
}
defer conn.Close()
file2, err := os.Open(...)
if err != nil {
return err
}
defer file2.Close()
.... do things ...
return nil
很清晰,簡潔,誰知道去就會明白髮生了什麼,這是非常難拿錯或將來打破。
來源
2017-10-09 09:38:04
Art