客户端模板代码
现在,让我们编写客户端的模板代码。这将与编写服务器模板代码非常相似,但我们不需要在 IP 和端口上创建监听器,而是要调用 grpc.Dial
函数并传递连接选项。
同样,我们不会将要连接的地址硬编码。我们将把地址作为参数传递:
args := os.Args[1:]
if len(args) == 0 {
log.Fatalln("usage: client [IP_ADDR]")
}
addr := args[0]
接下来,我们将创建一个 DialOption
实例,并为了保持模板的通用性,我们将使用 insecure.NewCredentials()
函数与服务器建立不安全的连接。不要担心,稍后我们会讨论如何建立安全连接:
opts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
}
最后,我们可以调用 grpc.Dial
函数来创建一个 grpc.ClientConn
对象。这个对象稍后将用于调用 API 接口。最后,由于这是一个连接对象,因此在客户端生命周期结束时,我们需要关闭它:
conn, err := grpc.Dial(addr, opts...)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer func(conn *grpc.ClientConn) {
if err := conn.Close(); err != nil {
log.Fatalf("unexpected error: %v", err)
}
}(conn)
客户端的代码就是这么简单。完整的代码如下(client/main.go
):
package main
import (
"log"
"os"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func main() {
args := os.Args[1:]
if len(args) == 0 {
log.Fatalln("usage: client [IP_ADDR]")
}
addr := args[0]
opts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
}
conn, err := grpc.Dial(addr, opts...)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer func(conn *grpc.ClientConn) {
if err := conn.Close(); err != nil {
log.Fatalf("unexpected error: %v", err)
}
}(conn)
}
显然,现在它什么也不做;不过我们可以通过先运行服务器来测试它:
$ go run server/main.go 0.0.0.0:50051
然后,运行我们的客户端:
$ go run client/main.go 0.0.0.0:50051
服务器应该无限期地等待,而客户端应该在终端上没有任何错误地返回。如果是这种情况,那么你就准备好编写一些 gRPC API 端点了。
Bazel
这次,Bazel
的设置不会像服务器那样复杂。主要是因为我们已经有了 deps.bzl
文件,并且可以在客户端中重复使用它。我们需要做的只是使用 Gazelle
生成 BUILD.bazel
文件,然后就完成了:
$ bazel run //:gazelle
现在,我们应该在 client
目录下看到一个 BUILD.bazel
文件。最重要的是,在这个文件中,我们可以看到 Bazel
将 gRPC 链接到了 client_lib
。我们应该看到类似这样的内容:
go_library(
name = "client_lib",
srcs = ["main.go"],
deps = [
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//credentials/insecure",
],
#...
)
现在,我们可以像运行 go run
命令一样运行我们的客户端:
$ bazel run //client:client 0.0.0.0:50051
现在,我们已经有了服务器和客户端。到目前为止,它们什么也不做,但这正是预期的目的。稍后在本书中,我们只需复制它们,就能专注于真正重要的部分——API。在做任何事情之前,我们先快速了解一下服务器和客户端设置中一些最重要的选项。