GO:Hello gRPC

实现一个 "Hello gRPC" 项目 in Go

在这篇文章中,我们将一步步通过如何在 Go 语言中实现一个简单的 gRPC 服务。 我们将构建一个 "Hello World" 示例,涵盖环境准备、定义服务接口、生成 gRPC 代码、实现服务、编写客户端调用服务以及运行和测试。

环境准备

  1. 确保你已经安装了 Go (版本 1.13 或更高,最好是1.18以上。写文章时候我的环境是1.22.1)。
  2. 安装 Protocol Buffers 编译器 protoc
  3. 安装 gRPC-Go 插件。
bash 复制代码
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

确保 $GOPATH/bin 在你的 PATH 环境变量中。

新建项目目录

创建一个新目录作为项目的根目录,例如 hello-grpc,并在其中创建一个 go.mod 文件来初始化 Go 模块:

bash 复制代码
mkdir hello-grpc
cd hello-grpc
mkdir helloworld
go mod init hello-grpc

定义服务接口

在helloworld这个目录中,创建一个名为 helloworld.proto 的文件,定义你的服务接口:

protobuf 复制代码
syntax = "proto3";

package helloworld;

option go_package = "hello-grpc/helloworld";

// 定义 Greeter 服务
service Greeter {
  // 定义一个 SayHello 方法
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// HelloRequest 消息定义
message HelloRequest {
  string name = 1;
}

// HelloReply 消息定义
message HelloReply {
  string message = 1;
}

生成 gRPC 代码

在项目根目录下,运行以下命令来生成 Go 代码:

bash 复制代码
protoc --go_out=. --go-grpc_out=. --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative helloworld/helloworld.proto

这将在项目中生成 helloworld.pb.gohelloworld_grpc.pb.go 文件。

实现服务

在项目根目录下创建一个 server 目录,并在其中创建 server.go

go 复制代码
package main

import (
	"context"
	"log"
	"net"

	pb "hello-grpc/helloworld"

	"google.golang.org/grpc"
)

const (
	port = ":50051"
)

// server 用于实现 helloworld.GreeterServer。
type server struct {
	pb.UnimplementedGreeterServer
}

// SayHello 实现了 helloworld.GreeterServer 接口。
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

编写客户端调用服务

在项目根目录下创建一个 client 目录,并在其中创建 client.go

go 复制代码
package main

import (
	"context"
	"log"
	"os"
	"time"

	pb "hello-grpc/helloworld"

	"google.golang.org/grpc"
)

const (
	address     = "localhost:50051"
	defaultName = "world"
)

func main() {
	// 建立与服务器的连接。
	conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)

	// 调用 SayHello 方法。
	name := defaultName
	if len(os.Args) > 1 {
		name = os.Args[1]
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.GetMessage())
}

运行和测试

首先,运行服务器:

bash 复制代码
go run server/server.go

然后,在另一个终端窗口,运行客户端:

bash 复制代码
go run client/client.go

你应该会在客户端看到服务器的问候。

相关推荐
明月_清风2 小时前
从二叉树到 B+ 树:一文搞懂工程中「树」的演化之道
数据结构·算法·go
江湖十年3 小时前
在 Go 中使用 dyno 包处理动态对象
后端·面试·go
a187927218313 小时前
【算法】回溯算法(三):三记重锤与 N 皇后——记忆化、状态设计与三层漏斗
算法·leetcode·go·剪枝·回溯·n皇后·算法讲解
纪卓志George4 小时前
打破语言范式:在 Go 里用动态代理实现 AOP
架构·go
码艺-Alimjan11 小时前
维吾尔语数字转文本
java·javascript·python·算法·go
名字还没想好☜13 小时前
Go 时间格式化为什么用 2006-01-02:time.Format/Parse 的参考时间、时区与解析踩坑
开发语言·后端·golang·go
我的div丢了肿么办1 天前
go语言中的map,map定义不同的数据类型,循环map,map的无序性
后端·go
名字还没想好☜1 天前
Go 1.21 context.WithoutCancel 实战:父 context 取消了,收尾任务还要继续跑
开发语言·后端·golang·go
newerp1 天前
Golang 接口的两副面孔:eface、iface 与动态派发之谜
后端·程序员·go
明月_清风1 天前
递归算法:从原理到实战,一次讲透
后端·算法·go