protoc 是什么?
protoc 是 Protobuf 官方提供的命令行编译工具,作用是将 .proto 文件(定义了接口、消息结构的 IDL 文件)编译为 目标编程语言(如 Go、Java、Python 等)的代码,让不同语言的服务能基于统一的 Protobuf 定义进行交互。
1.安装protoc
https://github.com/protocolbuffers/protobuf/releases
根据自己的需要安装版本
注:将对应的bin目录加入环境变量
2.安装protoc-grpc-go
protoc-grpc-go是一个插件,用于生成Go语言的数据结构代码
bash
go install github.com/golang/protobuf/protoc-gen-go
3.安装grpc
bash
go get -u google.golang.org/grpc
4.安装VSCODE 关于protoc文件插件
protobuf-vsc
以上环境准备好之后开始代码逻辑实现验证
1.原生rpc实现
a.服务端
Go
package main
import (
"fmt"
"net"
"net/http"
"net/rpc"
)
type Server struct {
}
type Req struct {
Num1 int
Num2 int
}
type Res struct {
Num int
}
func (s *Server) Add(req Req, res *Res) error {
res.Num = req.Num1 + req.Num2
return nil
}
func main() {
// 注册RPC服务
rpc.Register(new(Server))
rpc.HandleHTTP()
listen, err := net.Listen("tcp", ":8090")
if err != nil {
fmt.Println(err)
return
}
http.Serve(listen, nil)
}
启动

b.客户端
Go
package main
import (
"fmt"
"net/rpc"
)
type Req struct {
Num1 int
Num2 int
}
type Res struct {
Num int
}
func main() {
req := Req{Num1: 1, Num2: 2}
client, err := rpc.DialHTTP("tcp", ":8090")
if err != nil {
fmt.Println(err)
return
}
var res Res
client.Call("Server.Add", req, &res)
fmt.Println(res.Num)
}
启动

原生rpc缺点:
1.编写相对复杂,需要自己去关注实现过程
2.没有代码提示,容易出错
2.GPRC实现
a.定义proto文件:hello.proto
Go
// proto版本
syntax = "proto3";
// 默认包
package proto;
// 包名
option go_package = "/proto";
//定义rpc服务
service HelloService {
//定义函数体
rpc SayHello(Request) returns (Response);
}
message Request {
string name = 1;
string message = 2;
}
message Response {
string name = 1;
string message = 2;
}
b.编译proto文件生成go
bash
protoc -I . --go_out=plugins=grpc:. .\hello.proto
生成hello.pb.go
c.grpc服务端
Go
package main
import (
"context"
"fmt"
"net"
"project09/grpc/proto"
"google.golang.org/grpc"
)
// 此结构体可随意命名
type HelloWorld struct {
}
// 结构体中方法
func (hw *HelloWorld) SayHello(ctx context.Context, request *proto.Request) (respose *proto.Response, err error) {
fmt.Printf("接收请求:%v", request)
return &proto.Response{
Name: request.Name,
Message: request.Message,
}, nil
}
func main() {
listen, err := net.Listen("tcp", ":8010")
if err != nil {
fmt.Println("Fail to listen")
}
s := grpc.NewServer()
// 将结构体注册为grpc服务
server := HelloWorld{}
proto.RegisterHelloServiceServer(s, &server)
fmt.Println("grpc server running :8010")
// 开始处理客户端请求
s.Serve(listen)
}
启动:

d.客户端
Go
package main
import (
"context"
"fmt"
"log"
"project09/grpc/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func main() {
addr := ":8010"
// 创建一个客户端连接 且不使用安全证书来实现
conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf(fmt.Sprintf("grpc connect addr [%v] 连接失败%s", addr, err))
}
defer conn.Close()
client := proto.NewHelloServiceClient(conn)
result, err := client.SayHello(context.Background(), &proto.Request{
Name: "james",
Message: "ok",
})
fmt.Println(result, err)
}
启动:
以上为gprc具体实现。