安装 #
protoc安装 #
安装地址:https://github.com/protocolbuffers/protobuf
右侧有个Releases,点击进入可以看到各操作系统的版本,现在相应版本protoc,我这是windows amd64
保存到GOPATH下的/bin目录下
查看版本
protoc --version
安装go版本插件 #
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
protobuf格式 #
在protobuf中,协议是由一系列的消息(message)组成的,如下所示:
syntax = "proto3";
package Service;
//可以通过import导入其它proto
//import "taskModels.proto";
option go_package = "./;protos"; //两个参数一个是生成地址,一个是包名
enum Gender {
		MAN = 0;
		FEMAN = 1;
}
message Student {
	 string name = 1;  //1表示标识符,同一个message中不能重复
	 int32 coutry = 2;
	Gender gender = 3;
}
message Teacher {
	 string name = 1;
	 string class = 2;
	 string object = 3;
	 Gender gender = 4;
}
message School {
	repeated Student studentList = 1;
	repeated Teacher techerList = 2;
}
repeated:表示该字段可以包含多个元素,列表数组
编译生成pb.go文件 #
protoc -I ./protos --go_out=./ protos/user.proto
-I –proto_path 指定对导入文件的搜索路径,若不指定,则为当前路径
–go_out=../ 指定生成pb文件的目标目录
protos/user.proto 消息结构文件
在Service目录下执行编译命令

主函数
package main
import (
	"fmt"
	protos "micro_test/Service"
)
func main()  {
	std := &protos.Student{
		Name:   "laozhu",
		Coutry: 0,
		Gender: 0,
	}
	teacher := &protos.Teacher{
		Name:   "cjh",
		Class:  "1班",
		Object: "语文",
		Gender: 0,
	}
	schools := &protos.School{
		StudentList: []*protos.Student{std},
		TecherList:   []*protos.Teacher{teacher},
	}
	fmt.Println(schools)
}
输出
studentList:{name:"laozhu"}  techerList:{name:"cjh"  class:"1班"  object:"语文"}
RPC调用proto #
安装gRPC #
 go get -u google.golang.org/grpc
创建proto文件 #
hello.proto
//默认是Proto2
syntax = "proto3";
// 指定包名
//package pb;
option go_package = "./;protos";   //两个参数一个是生成地址,一个是包名
// 定义消息体
message Response {
    int32           error     = 1;   //1表示标识符,同一个message中不能重复
    string          ans       = 2;
}
// 消息体嵌套
message Request {
    string          name = 1;
}
//声明rpc调用方法
service ii14 {
    rpc sayHello(Request) returns (Response);
}
编译 #
使用了grpc插件 –go_out=plugins=grpc:.
protoc -I ./protos --go_out=plugins=grpc:./ protos/hello.proto
grpc测试 #
将上述protoc编译出来的go文件放到下述文件中同目录下引用使用
服务端代码 #
server/server.go
package main
import (
	context "context"
	"fmt"
	protos "micro_test/Service"
	"net"
	"google.golang.org/grpc"
)
//定义服务
type RPCService struct {
}
//实现服务方法
func (srv *RPCService) SayHello(ctx context.Context, req *protos.Request) (*protos.Response, error) {
	name := req.Name
	return &protos.Response{Error: 0, Ans: "Hello " + name}, nil
}
func main() {
	
    //启动grpc服务
	grpcSrv := grpc.NewServer()
    //实现服务接口
	protos.RegisterIi14Server(grpcSrv, new(RPCService))
	listener, err := net.Listen("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("net Listen error", err)
	}
    //启动侦听服务
	grpcSrv.Serve(listener)
}
客户端代码 #
client/server.go
package main
import (
	context "context"
	"fmt"
	grpc "google.golang.org/grpc"
	protos "micro_test/Service"
)
func main() {
    //连接grpc地址
	conn, err := grpc.Dial("127.0.0.1:8080", grpc.WithInsecure())
	if err != nil {
		fmt.Println("grpc Dial error", err)
		return
	}
    //调用call client
	client := protos.NewIi14Client(conn)
	
    //执行客户端的函数SayHello
	rep, err := client.SayHello(context.TODO(), &protos.Request{Name: "zy"})
	if err == nil {
		fmt.Println("execute succ ", rep)
	}
}
Micro调用 #
安装micro命令 #
go get github.com/micro/protoc-gen-micro
go get github.com/micro/go-micro/v2
创建proto文件 #
用户模型userModels.proto
syntax="proto3";
package services;
option go_package="../;protos";
message UserModel{
    // @inject_tag: json:"id"
    uint32 ID=1;
    // @inject_tag: json:"user_name"
    string UserName=2;
    // @inject_tag: json:"created_at"
    int64 CreatedAt=3;
    // @inject_tag: json:"updated_at"
    int64 UpdatedAt=4;
    // @inject_tag: json:"deleted_at"
    int64 DeletedAt=5;
}
用户业务userService.proto
syntax = "proto3";
option go_package="../;protos";
service Greeter {
	rpc Hello(Request) returns (Response) {}
}
message Request {
	string name = 1;
}
message Response {
	string msg = 1;
}
编译 #
在protos目录下执行
protoc  --micro_out=. --go_out=. greeter.proto
调用调试 #
服务端 #
package main
import (
	protos "micro_test/Service"
	"github.com/micro/go-micro/v2"
	"context"
)
type Greeter struct {
}
func (g *Greeter) Hello(ctx context.Context, req *protos.Greeter.Request, rsp *protos.Response) error {
	rsp.Msg = "Hello " + req.Name
	return nil
}
func main()  {
	microService := micro.NewService(
		micro.Name("rpcGreeterService"), // 微服务名字
		micro.Address("127.0.0.1:8082"),
	)
	microService.Init()
	_ = protos.RegisterGreeterHandler(microService.Server(), &Greeter{})
	_ = microService.Run()
}
客户端代码 #
	microService := micro.NewService(
		micro.Name("greeterService.client"),
	)
	// 用户服务调用实例
	greeterService := protos.NewGreeterService("rpcGreeterService",microService.Client())
	
		server := web.NewService(
		web.Name("httpService"),
		web.Address("127.0.0.1:4000"),
		//将服务调用实例使用gin处理
		web.Handler(router(greeterService)),
		web.RegisterTTL(time.Second*30),
		web.RegisterInterval(time.Second*15),
		web.Metadata(map[string]string{"protocol": "http"}),
	)
	//接收命令行参数
	_ = server.Init()
	_ = server.Run()
	
//定义路由
func router(service interface{}) *gin.Engine {
	ginRouter := gin.Default()
	ginRoouer.GET("greeter",function(ctx *gin.Context) {
		var req *&protos.Request
		cxt.Bind(&req)
		greeterService := service.(protos.GreeterService)
		resp,err := greeterService.SayHello(context.Background(),&req)
		ginCtx.JSON(http.StatusOK, gin.H{"data": resp})
	}
}