2 回答

TA貢獻1853條經驗 獲得超6個贊
從 golang 參考:
“延遲”語句調用一個函數,該函數的執行被推遲到周圍函數返回的那一刻
當您調用 os.Exit(0) 時,您繞過了正常的返回過程,并且不會執行您的延遲函數。
此外,即使 deferred 在主 goroutine 中工作,其他 goroutine 中的 defer 也不會工作,因為它們會在返回之前死亡。
更好的代碼架構可以讓你得到類似的東西。您需要將長時間運行的流程視為工人。導出工作進程中的每個長時間運行的進程,并在調用工作進程后立即推遲任何清理工作。在主 goroutine 中使用 select 來捕獲信號并同步工作
package main
import (
"fmt"
"io/ioutil"
"os"
"os/signal"
"syscall"
"time"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func main() {
ioutil.WriteFile("./foo.txt", []byte("foo"), 0644)
defer os.RemoveAll("./foo.txt")
// Worker 1
done := make(chan bool, 1)
go func(done chan bool) {
fmt.Println("worker 1 with bar ...")
ioutil.WriteFile("./bar.txt", []byte("bar"), 0644)
// various long running things
time.Sleep(3 * time.Second)
done <- true
}(done)
defer os.RemoveAll("./bar.txt")
// End worker1
s := make(chan os.Signal, 1)
signal.Notify(s, os.Interrupt)
signal.Notify(s, syscall.SIGTERM)
// Worker 2
done2 := make(chan bool, 1)
go func(done chan bool) {
fmt.Println("worker 2 ...")
time.Sleep(6 * time.Second)
done <- true
}(done2)
// End worker 2
select {
case <-s:
fmt.Println("Quiting with signal - exit")
case <-done:
<-done2
case <-done2:
<-done
}
return
}
這個選擇是處理兩個工人的一種快速而骯臟的方式,更好的方法是使用 sync.WaitGroup

TA貢獻1856條經驗 獲得超11個贊
我建議不要依賴 defer,而是定義一個可以在 defer 或信號塊中使用的可重用函數。像這樣的東西:
package main
import (
"fmt"
"io/ioutil"
"os"
"os/signal"
"syscall"
)
func main() {
ioutil.WriteFile("./foo.txt", []byte("foo"), 0644)
cleanup := func(){
os.RemoveAll("./foo.txt")
os.RemoveAll("./bar.txt")
}
defer cleanup() //for normal return
go func() {
ioutil.WriteFile("./bar.txt", []byte("bar"), 0644)
for {
// various long running things
}
}()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
signal.Notify(c, syscall.SIGTERM)
go func() {
<-c
fmt.Println("Received OS interrupt - exiting.")
cleanup()
os.Exit(0)
}()
for {
// various long running things
}
}
- 2 回答
- 0 關注
- 154 瀏覽
添加回答
舉報