考虑这个简单的代码:
type Message struct { /* ... */ }
type MyProcess struct {
in chan Message
}
func (foo *MyProcess) Start() {
for msg := range foo.in {
// handle `msg`
}
// someone closed `in` - bye
}
我想更改 MyProcess 以支持 2 种不同类型的消息。我有两个想法:
a) 类型开关
type Message struct { /* ... */ }
type OtherMessage struct { /* ... */ }
type MyProcess struct {
in chan interface{} // Changed signature to something more generic
}
func (foo *MyProcess) Start() {
for msg := range foo.in {
switch msg := msg.(type) {
case Message:
// handle `msg`
case OtherMessage:
// handle `msg`
default:
// programming error, type system didn't save us this time.
// panic?
}
}
// someone closed `in` - bye
}
b) 两个通道
type Message struct { /* ... */ }
type OtherMessage struct { /* ... */ }
type MyProcess struct {
in chan Message
otherIn chan OtherMessage
}
func (foo *MyProcess) Start() {
for {
select {
case msg, ok := <-foo.in:
if !ok {
// Someone closed `in`
break
}
// handle `msg`
case msg, ok := <-foo.otherIn:
if !ok {
// Someone closed `otherIn`
break
}
// handle `msg`
}
}
// someone closed `in` or `otherIn` - bye
}
两种实现之间的功能区别是什么?一件事是排序差异 - 只有第一个可以保证消息(Message
和OtherMessage
)将按正确的顺序处理。
哪个更地道?方法 'a' 更短,但不强制消息类型的正确性(可以在通道中放入任何东西)。方法 'b' 解决了这个问题,但有更多的样板文件和更多的人为错误空间:需要检查两个通道的封闭性(容易忘记)并且有人需要实际关闭它们(甚至更容易忘记)。
长话短说,我宁愿使用“a”,但它不利用类型系统,因此感觉很丑陋。也许有更好的选择?
慕姐8265434
相关分类