Go语言实现开发一个简单的gRPC Demo

 更新时间:2023年07月16日 11:08:02   作者:不背锅运维  
这篇文章主要为大家详细介绍了如何利用Go语言实现开发一个简单的gRPC Demo,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下

Part1先决条件

获得并安装好Golang(https://go.dev/doc/install

Protocol buffer compiler(protobuf编译器), protoc version 3(protoc工具版本建议为3版本),获得并安装:https://github.com/protocolbuffers/protobuf/releases

安装protocol编译器的Go插件

go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

Part2开发环境准备

准备go环境

wget https://go.dev/dl/go1.20.5.linux-amd64.tar.gz
tar -zxf go1.20.5.linux-amd64.tar.gz
mv go /usr/local/

安装protobuf编译器protoc

wget https://github.com/protocolbuffers/protobuf/releases/download/v23.4/protoc-23.4-linux-x86_64.zip
mkdir protoc-23.4
mv protoc-23.4-linux-x86_64.zip
cd protoc-23.4
unzip protoc-23.4-linux-x86_64.zip
rm -rf protoc-23.4-linux-x86_64.zip
cd ..
mv protoc-23.4 /usr/local/

添加相关环境变量

export GOROOT="/usr/local/go"
export GOPATH="/home/tantianran/goCode"
export GOPROXY="https://goproxy.cn,direct"
export GO111MODULE="on"
export PATH=$PATH:$GOROOT/bin:$GOPATH:$GOPATH/bin
export PROTOC_HOME=/usr/local/protoc-23.4
export PATH=$PATH:$PROTOC_HOME/bin

Part3实战:开发一个简单的gRPC Demo

1.创建user-service模块

tantianran@go-dev:~/goCode/src$ mkdir user-service
tantianran@go-dev:~/goCode/src$ cd user-service/
tantianran@go-dev:~/goCode/src/user-service$ go mod init

2.使用protobuf idl语言定义服务接口

创建service包

tantianran@go-dev:~/goCode/src/user-service$ mkdir service
tantianran@go-dev:~/goCode/src/user-service$ cd service/

service/users.proto内容:

syntax = "proto3";
option go_package = "user-service/service";
// 服务和方法
service Users {
    rpc GetUser (UserGetRequest) returns (UserGetReply) {}
}
// 请求消息
message UserGetRequest {
    string email = 1;
    int32 id = 2;
}
// 响应消息
message User {
    string id = 1;
    string first_name = 2;
    string last_name = 3;
    int32 age = 4;
}
message UserGetReply {
    User user = 1; // 嵌套
}

3.生成客户端和服务端代码

首先安装用于编译器的go语言插件protoc-gen-go

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

开始生成

tantianran@go-dev:~/goCode/src/user-service/service$ protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative users.proto
tantianran@go-dev:~/goCode/src/user-service/service$ ls -l
total 24
-rw-rw-r-- 1 tantianran tantianran   37 Jul 11 10:05 go.mod
-rw-rw-r-- 1 tantianran tantianran 3387 Jul 11 10:10 users_grpc.pb.go
-rw-rw-r-- 1 tantianran tantianran 8984 Jul 11 10:10 users.pb.go
-rw-rw-r-- 1 tantianran tantianran  362 Jul 11 10:09 users.proto

4.编写服务器

创建server包

tantianran@go-dev:~/goCode/src$ cd user-service/
tantianran@go-dev:~/goCode/src/user-service$ mkdir server
tantianran@go-dev:~/goCode/src/user-service$ cd server/

server/server.go

package main
import (
 "context"
 "log"
 "net"
 "os"
 users "user-service/service" // 导入之前生成的包
 "google.golang.org/grpc"
)
// userService类型是Users服务的服务处理程序
type userService struct {
 users.UnimplementedUsersServer // 这个字段对于gRPC中的任何服务实现都是强制性的
}
func (s *userService) GetUser(ctx context.Context, in *users.UserGetRequest) (*users.UserGetReply, error) {
 // 打印客户端传过来的数据
 log.Printf("已接收到邮件地址: %s, 还有ID: %d", in.Email, in.Id)
 // 自定义数据响应给客户端
 u := users.User{
  Id:        "user-782935",
  FirstName: "tan",
  LastName:  "tianran",
  Age:       30,
 }
 return &users.UserGetReply{User: &u}, nil
}
// 向gRPC服务器注册Users服务
func registerServices(s *grpc.Server) {
 users.RegisterUsersServer(s, &userService{})
}
// 启动gRPC服务器
func startServer(s *grpc.Server, l net.Listener) error {
 return s.Serve(l)
}
func main() {
 listenAddr := os.Getenv("LISTEN_ADDR")
 if len(listenAddr) == 0 {
  listenAddr = ":50051"
 }
 lis, err := net.Listen("tcp", listenAddr)
 if err != nil {
  log.Fatal(err)
 }
 s := grpc.NewServer()
 registerServices(s)
 log.Fatal(startServer(s, lis))
}

5.编写客户端

tantianran@go-dev:~/goCode/src$ cd user-service/
tantianran@go-dev:~/goCode/src/user-service$ mkdir client/
tantianran@go-dev:~/goCode/src/user-service$ cd client/

client/main.go

package main
import (
 "context"
 "log"
 "os"
 users "user-service/service" // 导入之前生成的包
 "google.golang.org/grpc"
)
// 建立与服务器的连接(通道)
func setupGrpcConnection(addr string) (*grpc.ClientConn, error) {
 return grpc.DialContext(
  context.Background(),
  addr,
  grpc.WithInsecure(),
  grpc.WithBlock(),
 )
}
// 创建客户端与Users服务通信
func getUserServiceClient(conn *grpc.ClientConn) users.UsersClient {
 return users.NewUsersClient(conn)
}
// 调用Users服务中的GetUser()方法
func getUser(client users.UsersClient, u *users.UserGetRequest) (*users.UserGetReply, error) {
 return client.GetUser(context.Background(), u)
}
func main() {
 if len(os.Args) != 2 {
  log.Fatal("缺少gRPC服务器地址")
 }
 conn, err := setupGrpcConnection(os.Args[1])
 if err != nil {
  log.Fatal(err)
 }
 defer conn.Close()
 c := getUserServiceClient(conn)
 result, err := getUser(c, &users.UserGetRequest{
  Email: "tantianran@qq.com",
  Id:    801896,
 })
 if err != nil {
  log.Fatal(err)
 }
 // 打印响应
 log.Printf("收到响应: %s %s %s %d\n", result.User.Id, result.User.FirstName, result.User.LastName, result.User.Age)
}

Part4验证效果

服务器

tantianran@go-dev:~/goCode/src/user-service/server$ go run server.go
2023/07/12 00:59:01 已接收到邮件地址: tantianran@qq.com, 还有ID: 801896

客户端

tantianran@go-dev:~/goCode/src/user-service/client$ go run main.go localhost:50051
2023/07/12 00:59:01 收到响应: user-782935 tan tianran 30

以上就是Go语言实现开发一个简单的gRPC Demo的详细内容,更多关于Go gRPC的资料请关注脚本之家其它相关文章!

相关文章

  • golang pprof 监控系列 go trace统计原理与使用解析

    golang pprof 监控系列 go trace统计原理与使用解析

    这篇文章主要为大家介绍了golang pprof 监控系列 go trace统计原理与使用解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Go语言之init函数

    Go语言之init函数

    Go语言有一个特殊的函数init,先于main函数执行,实现包级别的一些初始化操作。这篇文章介绍了Go中的Init函数,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • golang通过gorm操作sqlite设置主键自增的步骤

    golang通过gorm操作sqlite设置主键自增的步骤

    这篇文章主要介绍了golang通过gorm操作sqlite设置主键自增的详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • golang channel多协程通信常用方法底层原理全面解析

    golang channel多协程通信常用方法底层原理全面解析

    channel 是 goroutine 与 goroutine 之间通信的重要桥梁,借助 channel,我们能很轻易的写出一个多协程通信程序,今天,我们就来看看这个 channel 的常用用法以及底层原理
    2023-09-09
  • Go学习笔记之Zap日志的使用

    Go学习笔记之Zap日志的使用

    这篇文章主要为大家详细介绍了Go语言中Zap日志的使用以及安装,文中的示例代码讲解详细,对我们学习Go语言有一定的帮助,需要的可以参考一下
    2022-07-07
  • Goland激活码破解永久版及安装详细教程(亲测可以)

    Goland激活码破解永久版及安装详细教程(亲测可以)

    这篇文章主要介绍了Goland激活码破解永久版及安装详细教程(亲测可以),本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • go语言 nil使用避坑指南

    go语言 nil使用避坑指南

    这篇文章主要为大家介绍了go语言 nil使用避坑指南详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • 详解Golang如何优雅判断interface是否为nil

    详解Golang如何优雅判断interface是否为nil

    这篇文章主要为大家详细介绍了Golang如何优雅判断interface是否为nil的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解下
    2024-01-01
  • Go语言实现字符串切片赋值的方法小结

    Go语言实现字符串切片赋值的方法小结

    这篇文章主要给大家介绍了Go语言实现字符串切片赋值的两种方法,分别是在for循环的range中以及在函数的参数传递中实现,有需要的朋友们可以根据自己的需要选择使用。下面来一起看看吧。
    2016-10-10
  • Golang图片验证码的使用方法

    Golang图片验证码的使用方法

    最近在使用到Golang进行原生开发,注册和登录页面都涉及到图片验证码的功能,支持很多类型的验证方式,例如支持数字类型、字母类型、音频验证码、中文验证码,本文给大家介绍Golang图片验证码的使用,感兴趣的朋友跟随小编一起看看吧
    2024-05-05

最新评论