我正在通过http。
为jsonrpc开发一个简单的go库有以下方法:
rpcClient.Call("myMethod", myParam1, myParam2)
此方法在内部执行http.Get()并返回结果或错误(元组)。
这当然是调用者的同步,并在Get()调用返回时返回。
这是提供库的方式吗?如果她愿意,我应该把它留给我的库的用户使其异步吗?
或者我应该提供第二个函数:
rpcClient.CallAsync()
并在此处返回频道?因为通道不能提供元组,所以我必须在结构中打包(响应,错误)元组并返回该结构。
这有意义吗?
否则,用户必须用丑陋的方法包装每个调用,如:
result := make(chan AsyncResponse)
go func() {
res, err := rpcClient.Call("myMethod", myParam1, myParam2)
result <- AsyncResponse{res, err}
}()
go库和异步是否有最佳实践?
答案 0 :(得分:3)
go的执行模型的重点是隐藏开发人员的异步操作,并且表现得像带有阻塞操作的线程模型。在幕后有绿色线程和异步IO以及非常复杂的调度程序。
所以不,你不应该为你的库提供异步API。从代码的角度来看,go中的网络是以伪阻塞的方式完成的,你可以根据需要打开尽可能多的goroutine,因为它们非常便宜。
所以你最后一个例子是要走的路,我不认为它很难看。因为它允许开发人员选择并发模型。在http服务器的上下文中,每个命令都在单独的goroutine中处理,我只需要调用rpcClient.Call("myMethod", myParam1, myParam2)
。
或者,如果我想要一个扇出 - 我将创建扇出逻辑。
您还可以创建一个便利功能来执行呼叫并在频道上返回:
func CallAsync(method, p1, p2) chan AsyncResponse {
result := make(chan AsyncResponse)
go func() {
res, err := rpcClient.Call(method, p1, p2)
result <- AsyncResponse{res, err}
}()
return result
}