怎麼阻止一個 Go 程序退出?
給大家分享一個阻止 Go 程序退出的方法集合,其中還是有一些腦洞大開的方法。你有什麼別的方法可以阻止 Go 程序退出麼, 歡迎在留言區留言。
像下面這樣的程序,程序一運行就是退出了,原因在於主 goroutine 執行完了,子 goroutine 雖然存在,但是沒能阻止主 goroutine 的執行:
package main
import "net/http"
func main() {
go http.ListenAndServe(":8080", nil)
}
我整理了 11 個方法,看看你是否想得到。
方法一:死循環
這個方法是一個傻傻的方法,會耗費一個 CPU 核空轉。
package main
import "net/http"
func main() {
go http.ListenAndServe(":8080", nil)
for {
}
}
方法二:select{}
這是我寫例子的時候常用的一個技巧,使用不帶 case 的 select 語句,字數夠少,所以我喜歡用。
package main
import "net/http"
func main() {
go http.ListenAndServe(":8080", nil)
select {}
}
方法三: 從一個不帶緩存的 channel 中讀數據或者放數據
兩種方法都會被阻塞。
package main
import "net/http"
func main() {
go http.ListenAndServe(":8080", nil)
c := make(chan struct{})
// <-c
c <- struct{}{}
}
方法四:從一個 nil channel 中讀數據或者放數據
兩種方法都會被阻塞。
package main
import "net/http"
func main() {
go http.ListenAndServe(":8080", nil)
var c chan struct{}
// <-c
c <- struct{}{}
}
方法五:互斥鎖
讀寫鎖也類似。
package main
import (
"net/http"
"sync"
)
func main() {
go http.ListenAndServe(":8080", nil)
var m sync.Mutex
m.Lock()
m.Lock()
}
方法六:WaitGroup
也許你已經掌握套路了,很多同步原語都可以,比如 Cond、信號量,我們就不重複介紹了。
package main
import (
"net/http"
"sync"
)
func main() {
go http.ListenAndServe(":8080", nil)
var wg sync.WaitGroup
wg.Add(1)
wg.Wait()
}
方法七: 阻塞 I/O
最簡單的使用os.Stdin
, 還可以使用文件、socket 等,只要阻塞 I/O 即可。
package main
import (
"net/http"
"os"
)
func main() {
go http.ListenAndServe(":8080", nil)
os.Stdin.Read(make([]byte, 1))
}
方法八: 使用 signal.Notify
這是我在產品中經常使用的一個技巧,捕獲os.Signal
, 實現優雅的退出。
package main
import (
"net/http"
"os"
"os/signal"
)
func main() {
go http.ListenAndServe(":8080", nil)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
}
方法九:使用 signal.Notify
的變形
使用 Context, 可以把 context 傳遞給子 goroutine,Context 也適合和 select 配套使用。
package main
import (
"context"
"net/http"
"os"
"os/signal"
)
func main() {
go http.ListenAndServe(":8080", nil)
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
<-ctx.Done()
}
方法十:fmt.Scanln()
阻塞 I/O 更簡潔的方式。
package main
import (
"fmt"
"net/http"
)
func main() {
go http.ListenAndServe(":8080", nil)
fmt.Scanln()
}
方法十一:runtime.Goexit()
主程序退出但是函數卻不返回,直到子 goroutine 完成。
package main
import (
"net/http"
"runtime"
)
func main() {
go http.ListenAndServe(":8080", nil)
runtime.Goexit()
}
你還知道哪些方法?
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/C2AmKZjg9CyiIDxyU0-b1Q