我应该关心在go库中提供异步调用吗?

时间:2016-11-13 10:03:56

标签: go

我正在通过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库和异步是否有最佳实践?

1 个答案:

答案 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
}