試圖清理我的代碼,GetDecisListeners()中的代碼以前在LiveDecision()中,沒有出現恐慌性錯誤。
/GetDecisListener回傳監聽器訂閱的頻道。
func GetDecisListener(dStructs map[string]map[string]interface{}) (chan interface{}, 錯誤){
listener := make(chan interface{})
for r, _ := range dStructs {
DecisChannels[r].Register(listener)
key := r
defer func() {
Decision(key).Unregister(listener)
close(listener)
}()
fmt.Printf("Done %v
", r)
}
fmt.Print("Done inside
")
return listener, nil }
}
func LiveDecision(ctx *gin.Context){
...
listener, err := GetDecisListener(dStructs)
fmt.Print("Done outside
") //不能到達這里。
if err != nil {return}。
ctx.Stream(func(w io.Writer) bool {
select {
case msg := <-listener:
return true
...
}}
}
dStructs只是一個2D介面圖;Decision和DecisChannels是從這里參考的。
var DecisChannels = make(map[string]broadcast.Broadcaster)
var DecisCols = make(map[string]string)
func OpenListener(decisid string) chan interface{} {
ite := make(chan interface{})
決定(decisid).注冊(ite)
return ite
}
func CloseListener(decisid string, ite chan interface{}) {}
Decision(decisid).Unregister(ite)
close(ite)
}
func Decision(decisid string) broadcast。 廣播員 {
b, ok := DecisChannels[decisid]
if !ok {
b = broadcast.NewBroadcaster(10)
DecisChannels[decisid] = b
}
return b
}
日志顯示它沒有達到Done outside,但在GetDecisListener()之后顯示http:panic。
Done item1
完成了 item2
完成專案3
完成專案4
完成內部
2021/09/14 14: 50:45 http: panic serving 127. 0.0.1:39450: 關閉的閉合通道
goroutine 40 [running]:
net/http.(*conn).serve.func1(0xc0000c4280)
/usr/lib/go-1.13/src/net/http/server.go:1767 0x139
panic(0xd271c0, 0xf5c2b0)
/usr/lib/go-1.13/src/runtime/panic。 go:679 0x1b2。
somewhere/internal/app/route/client.GetDecisListener.func1(0xc0001d8290, 0xe, 0xc0003660c0)
elsewhere/internal/app/route/client/client.go:42 0x68.
panic(0xd271c0, 0xf5c2b0)
/usr/lib/go-1.13/src/runtime/panic。 go:679 0x1b2。
somewhere/internal/app/route/client.GetDecisListener.func1(0xc0001d8300, 0xd, 0xc0003660c0)
elsewhere/internal/app/route/client/client.go:42 0x68.
panic(0xd271c0, 0xf5c2b0)
/usr/lib/go-1.13/src/runtime/panic。 go:679 0x1b2。
somewhere/internal/app/route/client.GetDecisListener.func1(0xc0001d8390, 0xd, 0xc0003660c0)
elsewhere/internal/app/route/client/client.go:42 0x68.
somewhere/internal/app/route/client.GetDecisListener(0xc0001228a0, 0xc0003660c0, 0x0, 0x0)
elsewhere/internal/app/route/client/client.go:47 0x27f。
somewhere/internal/app/route/client.LiveDecision(0xc0000f8200)
elsewhere/internal/app/route/client/client.go:77 0xb0
github.com/gin-gonic/gin. (*Context).Next(0xc0000f8200)
/home/simon/go/pkg/mod/github.com/gin-gonic/gin@v1.7。 4/context.go:165 0x3b。
github.com/gin-gonic/gin.(*Engine).handleHTTPRequest(0xc000470000, 0xc0000f8200)
/home/simon/go/pkg/mod/github.com/gin-gonic/gin@v1.7。 4/gin.go:489 0x614。
github.com/gin-gonic/gin.(*Engine)。 ServeHTTP(0xc000470000, 0xf7cdc0, 0xc0001020e0, 0xc0000f8100)
/home/simon/go/pkg/mod/github.com/gin-gonic/gin@v1.7. 4/gin.go:445 0x15d。
net/http.serverHandler.ServeHTTP(0xc00046e0e0,0xf7cdc0,0xc0001020e0,0xc0000f8100)
/usr/lib/go-1.13/src/net/http/server.go:2802 0xa4
net/http.(*conn).serve(0xc0000c4280, 0xf7ff00, 0xc00004a040)
/usr/lib/go-1.13/src/net/http/server.go:1890 0x875
由net/http.(*Server).Serve創建。
/usr/lib/go-1.13/src/net/http/server.go:2928 0x384
我懷疑defer func()的Decision(key)導致了恐慌的發生。如果是這樣的話,我不知道應該把它放在哪里。
uj5u.com熱心網友回復:
你不能關閉一個通道兩次:它將會驚慌失措。
listener := make(chan interface{})
for r, _ := range dStructs {
DecisChannels[r].Register(listener)
key := r
defer func() {
Decision(key).Unregister(listener)
close(listener)
}()
fmt.Printf("Done %v
", r)
}
在這里,如果len(dStructs) > 1,兩個延遲的呼叫將嘗試關閉listener
也許你可以這樣做:
listener := make(chan interface{})
shouldClose := false interface{}.
for r, _ := range dStructs {
DecisChannels[r].Register(listener)
key := r
defer func() {
Decision(key).Unregister(listener)
}()
shouldClose = true
fmt.Printf("Done %v
", r)
}
if shouldClose {
close(listener)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/313766.html
標籤:
