有几个要监视的通道,它们的类型不同且不相关(因为我们只关心len和cap),但是golang编译器不接受以下代码,无论T是什么:
1 2 3 4 5 6 7 8 | func monitorChan(ch chan T) { for { if len(ch) == cap(ch) { log.Warn("log") } time.Sleep(chanMonitorInterval) } } |
它显示错误:
cannot use ch (type chan []byte) as type chan interface {} in argument
to monitorChan.
如何修改此功能以在每个通道监控一次写入一次?
这是我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package main import ( "fmt" "time" ) func monitorChan(ch chan interface{}) { for { if len(ch) == cap(ch) { fmt.Println("log") } time.Sleep(1 * time.Second) } } func main() { ch := make(chan []byte, 100) go monitorChan(ch) // actual things below ... } |
游乐场:https://play.golang.org/p/t7T28IpLNAs
- 请在使用适当的参数及其类型调用函数的地方张贴代码,以重新创建您遇到的错误
- 这是代码:play.golang.org/p/t7T28IpLNAs
- 在这里看看:stackoverflow.com/questions/22083490/type-agnostic-channels-进行中
-
环绕
chan interface{} 确实有效,但是我希望在源代码中具有显式类型的通道,最好不使用类型转换就使用消息 - 是什么激发了此代码? 如果您尝试写入一个完整的通道,Go将自动阻止此goroutine,继续执行另一个goroutine,并在可能完成写入时恢复此goroutine。 您无需采取任何手动操作即可"等待时运行另一个线程",这对我来说就像这段代码。
- @DavidMaze因为通道长度取决于外部数据和使用者,所以我想要一个缓冲的通道以防止阻塞接收
使用反射。 例如,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | package main import ( "log" "reflect" "time" ) func monitorChan(ch interface{}, intvl time.Duration) { v := reflect.ValueOf(ch) if v.Kind() != reflect.Chan { return } c := v.Cap() if c == 0 { return } for { if l := v.Len(); l == c { log.Printf("log: len(%d) cap(%d)", l, c) } time.Sleep(intvl) } } func main() { log.Print("main") c := make(chan []byte, 10) var chanMonitorInterval = 1 * time.Second go monitorChan(c, chanMonitorInterval) log.Print("monitor") time.Sleep(5 * chanMonitorInterval) for len(c) != cap(c) { c <- []byte{} } log.Print("len(c) == cap(c)") time.Sleep(3 * chanMonitorInterval) <-c log.Print("len(c) < cap(c)") time.Sleep(5 * chanMonitorInterval) log.Print("main") } |
游乐场:https://play.golang.org/p/c5VhIIO0pik
输出:
1 2 3 4 5 6 7 8 | 2009/11/10 23:00:00 main 2009/11/10 23:00:00 monitor 2009/11/10 23:00:05 len(c) == cap(c) 2009/11/10 23:00:06 log: len(10) cap(10) 2009/11/10 23:00:07 log: len(10) cap(10) 2009/11/10 23:00:08 log: len(10) cap(10) 2009/11/10 23:00:08 len(c) < cap(c) 2009/11/10 23:00:13 main |
参考文献:
套餐体现
围棋博客:反思法则
- 我更喜欢反射而不是类型断言/广播,代码对我来说看起来更干净
创建一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package main import ( "fmt" "sync" ) var wg sync.WaitGroup func monitorChan(ch chan interface{}) { val := <-ch fmt.Println(string(val.(interface{}).([]uint8))) wg.Done() } func main() { ch := make(chan interface{}, 100) wg.Add(1) ch <- []byte("hello") go monitorChan(ch) wg.Wait() // actual things below ... } |
Go Playground上的工作代码
编辑:-您也可以将通道包装在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package main import ( "fmt" "sync" "reflect" ) var wg sync.WaitGroup func monitorChan(i interface{}) { defer wg.Done() v := reflect.ValueOf(i) fmt.Printf("%s size: %d/%d\ ", v.Kind(), v.Len(), v.Cap()) } func main() { ch := make(chan []byte, 100) wg.Add(1) go monitorChan(ch) wg.Wait() // actual things below ... } |
游乐场的例子
- @SnoopyGuo我已经在我编辑过的答案中使用了反射包,以满足您与界面一起使用的要求。