Who is Goroutine
轻量级线程-协程
How to use Goroutine
https://dave.cheney.net/practical-go/presentations/qcon-china.html#_concurrency
- Keep yourself busy or do the work yourself
- 如果你的Goroutine在另一个Goroutine获得结果之前无法取得进展,那么通常情况下,自己做,比委派出去更简单
- Never satart a Goroutine without knowing when it will stop
- 如果要委派出去Goroutine,应该感知到Goroutine结束
- Leave concurrency to the caller
- 什么时候Goroutine结束?
- 如何让某个Goroutine结束?
- Goroutine由调用者 go
Bad Code
func main() {go func() {test()}()select {}}func test() {// xxxx xxxx xxxx}
func main() {Go(test)select {}}func test() {// xxxx xxxx xxxx}func Go(f func()) {go func() {if err := recover(); err != nil {fmt.Println(err)}f()}()}
func main() {http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "Hello")})go func() {if err := http.ListenAndServe(":8080", nil); err != nil {log.Fatal(err)}}()select {}}
func main() {mux := http.NewServeMux()mux.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) {fmt.Fprintln(resp, "Hello, QCon!")})go http.ListenAndServe("127.0.0.1:8001", http.DefaultServeMux) // debughttp.ListenAndServe("0.0.0.0:8080", mux) // app traffic}
// API servie 接收一个servicefunc service() {go Go(doSometing())}func doSometing() {// xxxxxx}func Go(f func()) {if err := recover(); err != nil {fmt.Println(err)}f()}
Example
- 异步执行某个东西 ```go func main() { go Go(test) select {} }
func test() { // xxxx xxxx xxxx }
func Go(f func()) { if err := recover(); err != nil { fmt.Println(err) } f() }
- 启动一个http服务```gofunc main() {http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "Hello, GopherCon SG")})if err := http.ListenAndServe(":8080", nil); err != nil {log.Fatal(err)}}
同时启动2个http监听2个端口 ```go func main() { stop := make(chan struct{}) errs := make(chan error) stoped := false // 启动server1 go func() { // Rule.3 go 由调用者发起
errs <- server(":10000", stop)
}() // 启动server2 go func() {
errs <- server(":10001", stop)
}()
for i := 0; i < cap(errs); i++ {
if err := <-errs; err != nil {fmt.Printf("err:%s", err)}if !stopped {stopped = trueclose(stop) // Rule.2 明确goroutine怎么退出}
} }
func server(addr string, stop <-chan struct{}) error { s := http.Server{Addr: addr} // 监听退出信号 // Rule.1 明确goroutine什么时候退出;close关闭时 go func() { <-stop s.ShutDown(context.Background()) // Rule.2 明确server作为异步出去的goroutine怎么退出 }() return s.ListenAndServe() }
- 发送异步更新数据```gofunc main() {logCh := make(chan string, 10)go subLog(logCh)for i := 0; i < 1000; i++ {pub(logCh)}time.Sleep(10 * time.Second)close(logCh)}func pub(ch chan<- string) {i := strconv.Itoa(rand.Intn(10000))ch <- i}func subLog(ch <-chan string) {for s := range ch {fmt.Println("log:", s)}}
