我在项目中使用了pion/webrtc Go库,发现该库提供的基于回调的API(反映了WebRTC的JavaScript API)在Go中使用时很尴尬。
>例如,执行以下操作
conn.OnTrack(func(...) { ... })
conn.OnICEConnectionStateChange(func(...) { ... })
在JavaScript中是典型的,但是在Go语言中,这有一些问题:
在Go中处理这种情况的常规方法是什么?我是Go的新手,我读到Go中首选同步API,因为Goroutines很便宜。因此,也许一种可能的设计是使用一个通道来同步回调:
msgChan := make(chan Msg)
// or use a separate channel for each type of event?
conn.OnTrack(func(...) {
msgChan <- onTrackMsg
})
conn.OnICEConnectionStateChange(func(...) {
msgChan <- onStateChangeMsg
})
for {
msg := <-msgChan
// do something depending on the type of msg
}
我认为强制与通道同步基本上模仿了JavaScript的单线程性质。
无论如何,人们通常如何在Go中建模事件驱动的工作流程?
答案 0 :(得分:1)
不需要频道。只需将异步/回调代码包装在等待响应的单个函数中,然后使用WaitGroup(您可以在此处使用通道,但使用WaitGroup要容易得多):
func DoSomething() (someType, error) {
var result SomeType
var err error
wg := sync.WaitGroup{}
wg.Add(1)
StartAsyncProcess(func() {
// This is the call back that gets called eventually
defer wg.Done()
result = /* Set the result */
err = /* and/or set the error */
})
wg.Wait() // Wait until the callback is called, and exits
return result, err // And finally return our values
}
如果您的回调依赖或修改共享状态,则可能需要/希望在回调中添加其他锁定或同步。