首页 > 解决方案 > 空选择{}的可能用例是什么

问题描述

我知道空select{}会永远阻塞 go-Routine,但不明白这能满足所有不同的用例吗?

我还检查了去 repo 以找到更多用法,我只能找到两个实现,一个在syscall/js 中,另一个在httptest中。

func handleEvent() {
        cb := jsGo.Get("_pendingEvent")
        if cb.IsNull() {
                return
        }
        jsGo.Set("_pendingEvent", Null())

        id := uint32(cb.Get("id").Int())
        if id == 0 { // zero indicates deadlock
                select {}
        }
        funcsMu.Lock()
        f, ok := funcs[id]
        funcsMu.Unlock()
        if !ok {
                Global().Get("console").Call("error", "call to released function")
                return
        }

        this := cb.Get("this")
        argsObj := cb.Get("args")
        args := make([]Value, argsObj.Length())
        for i := range args {
                args[i] = argsObj.Index(i)
        }
        result := f(this, args)
        cb.Set("result", result)
}

在 httptest 中的使用

// Start starts a server from NewUnstartedServer.
func (s *Server) Start() {
        if s.URL != "" {
                panic("Server already started")
        }
        if s.client == nil {
                s.client = &http.Client{Transport: &http.Transport{}}
        }
        s.URL = "http://" + s.Listener.Addr().String()
        s.wrap()
        s.goServe()
        if serveFlag != "" {
                fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL)
                select {}
        }
}

这里的问题是这里是如何select {}使用的,除此之外是否还有其他用例,我们可以在哪里利用select {}

标签: goconcurrencyblockinggoroutine

解决方案


select {}永远阻塞当前的 goroutine。

一个用例是当你需要这样做时,显然。这应该是极其罕见的情况。

第一个示例使用它来强制主 goroutine 中的死锁,因为 eventID0是不可能的。

但第二个例子是代码异味。你几乎总是可以用一种不需要阻塞这样的 goroutine 的方式来构造代码。例如,s.goServe()可以重构为,然后可以分别使用或s.serve()以阻塞或非阻塞方式调用它。s.serve()go s.serve()


推荐阅读