提交更清晰的测试以及注释
This commit is contained in:
parent
8f7a4f8c58
commit
426f24f720
@ -6,6 +6,13 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
原生chan主张谁申请谁负责关闭。但实际项目中权责往往没有这么清晰。
|
||||||
|
有时候会出现多个协程对同一个chan写入的情况,此时chan被某一个协程关闭,另一个正在写入会导致panic。
|
||||||
|
如果对原生chan关闭多次也会panic。原生chan更适合一写一读或多读的场景,生产者负责chan生命周期,消费者只负责读。
|
||||||
|
SafeChan可以多写多读多关闭而不会panic。
|
||||||
|
*/
|
||||||
|
|
||||||
type ByteChan = SafeChan[[]byte]
|
type ByteChan = SafeChan[[]byte]
|
||||||
|
|
||||||
type SafeChan[T any] struct {
|
type SafeChan[T any] struct {
|
||||||
|
@ -1,16 +1,39 @@
|
|||||||
package safeChan
|
package safeChan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/fox/fox/ksync"
|
||||||
|
"github.com/fox/fox/log"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSafeChan(t *testing.T) {
|
func initLog() {
|
||||||
ch := NewSafeChan[string](12)
|
log.Open("test.log", log.DebugL)
|
||||||
|
}
|
||||||
|
|
||||||
// go func() {
|
func OriginChanPanic(t *testing.T) {
|
||||||
_ = ch.Write("hello")
|
och := make(chan string, 10)
|
||||||
t.Log("write hello. 剩余数量:", ch.Size())
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SafeChanNoPanic(t *testing.T) {
|
||||||
|
ch := NewSafeChan[string](12)
|
||||||
|
go func() {
|
||||||
|
_ = ch.Write("hello")
|
||||||
|
t.Log("write hello. 剩余数量:", ch.Size())
|
||||||
|
}()
|
||||||
ch.Close()
|
ch.Close()
|
||||||
if err := ch.Write("zzz"); err != nil {
|
if err := ch.Write("zzz"); err != nil {
|
||||||
t.Log("write zzz err.", err)
|
t.Log("write zzz err.", err)
|
||||||
@ -20,9 +43,6 @@ func TestSafeChan(t *testing.T) {
|
|||||||
for {
|
for {
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ch.ctx.Done():
|
|
||||||
t.Log("done")
|
|
||||||
breakNum++
|
|
||||||
case v, ok := <-ch.Reader():
|
case v, ok := <-ch.Reader():
|
||||||
if ok {
|
if ok {
|
||||||
t.Log("read", v, " 剩余数量:", ch.Size())
|
t.Log("read", v, " 剩余数量:", ch.Size())
|
||||||
@ -41,3 +61,12 @@ func TestSafeChan(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSafeChan(t *testing.T) {
|
||||||
|
initLog()
|
||||||
|
OriginChanPanic(t)
|
||||||
|
time.Sleep(time.Second * 1)
|
||||||
|
SafeChanNoPanic(t)
|
||||||
|
// 防止主协程过早退出,导致go协程里无法打印
|
||||||
|
time.Sleep(time.Second * 1)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user