2025-05-25 20:02:15 +08:00
|
|
|
|
package safeChan
|
|
|
|
|
|
|
|
|
|
import (
|
2025-09-02 21:52:56 +08:00
|
|
|
|
"github.com/fox/fox/ksync"
|
|
|
|
|
"github.com/fox/fox/log"
|
2025-05-25 20:02:15 +08:00
|
|
|
|
"testing"
|
2025-09-02 21:52:56 +08:00
|
|
|
|
"time"
|
2025-05-25 20:02:15 +08:00
|
|
|
|
)
|
|
|
|
|
|
2025-09-02 21:52:56 +08:00
|
|
|
|
func initLog() {
|
|
|
|
|
log.Open("test.log", log.DebugL)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func OriginChanPanic(t *testing.T) {
|
|
|
|
|
och := make(chan string, 10)
|
|
|
|
|
go func() {
|
|
|
|
|
och <- "hello"
|
|
|
|
|
t.Log("write hello")
|
|
|
|
|
close(och)
|
|
|
|
|
//close(och) // 多次关闭也会panic
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
time.Sleep(time.Millisecond)
|
|
|
|
|
t.Log("origin chan was closed")
|
|
|
|
|
|
|
|
|
|
ksync.GoSafe(func() {
|
|
|
|
|
och <- "world"
|
|
|
|
|
}, nil)
|
|
|
|
|
}
|
2025-05-25 20:02:15 +08:00
|
|
|
|
|
2025-09-02 21:52:56 +08:00
|
|
|
|
func SafeChanNoPanic(t *testing.T) {
|
|
|
|
|
ch := NewSafeChan[string](12)
|
|
|
|
|
go func() {
|
|
|
|
|
_ = ch.Write("hello")
|
|
|
|
|
t.Log("write hello. 剩余数量:", ch.Size())
|
|
|
|
|
}()
|
2025-05-25 20:02:15 +08:00
|
|
|
|
ch.Close()
|
|
|
|
|
if err := ch.Write("zzz"); err != nil {
|
|
|
|
|
t.Log("write zzz err.", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
breakNum := 0
|
|
|
|
|
for {
|
|
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case v, ok := <-ch.Reader():
|
|
|
|
|
if ok {
|
|
|
|
|
t.Log("read", v, " 剩余数量:", ch.Size())
|
|
|
|
|
} else {
|
|
|
|
|
t.Log("break")
|
|
|
|
|
breakNum++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
t.Log("panic")
|
|
|
|
|
breakNum++
|
|
|
|
|
}
|
|
|
|
|
if breakNum > 10 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2025-09-02 21:52:56 +08:00
|
|
|
|
|
|
|
|
|
func TestSafeChan(t *testing.T) {
|
|
|
|
|
initLog()
|
|
|
|
|
OriginChanPanic(t)
|
|
|
|
|
time.Sleep(time.Second * 1)
|
|
|
|
|
SafeChanNoPanic(t)
|
|
|
|
|
// 防止主协程过早退出,导致go协程里无法打印
|
|
|
|
|
time.Sleep(time.Second * 1)
|
|
|
|
|
}
|