美文网首页
五. Go(Go protobuf)

五. Go(Go protobuf)

作者: 冰菓_ | 来源:发表于2022-07-28 23:06 被阅读0次
    gopath开发模式和go modules开发模式对比
    goland创建项目时没用go mod模式选项的坑

    在GoLand 2021.2 稳定版的更新文档里有一些对go modules的更新,欢迎界面的默认 Go 选项现在是 Go modules 项目的默认选项

    解决warning: go env -w GOPROXY=... does not override conflicting OS environment variable问题
    Go语言编码规范

    Go语言编码规范 - Go语言中文网

    什么是rpc?rpc开发的挑战是什么?
    1. Call ID映射:在本地调用中,函数体是直接通过函数指针来指定的,我们调用add,编译器就自动帮我们调用它相应的函数指针。但是在远程调用中,函数指针是不行的,因为两个进程的地址空间是完全不一样的。所以,在RPC中,所有的函数都必须有自己的一个ID。这个ID在所有进程中都是唯一确定的。客户端在做远程过程调用时,必须附上这个ID。
    2. 序列化和反序列化。客户端怎么把参数值传给远程的函数呢?在本地调用中,我们只需要把参数压到栈里,然后让函数自己去栈里读就行。但是在远程过程调用时,客户端跟服务端是不同的进程,不能通过内存来传递参数。甚至有时候客户端和服务端使用的都不是同一种语言(比如服务端用C++,客户端用Java或者Python)。这时候就需要客户端把参数先转成一个字节流,传给服务端后,再把字节流转成自己能读取的格式。这个过程叫序列化和反序列化。同理,从服务端返回的值也需要序列化反序列化的过程。
    3. 网络传输。远程调用往往用在网络上,客户端和服务端是通过网络连接的。所有的数据都需要通过网络传输,因此就需要有一个网络传输层。网络传输层需要把Call ID和序列化后的参数字节流传给服务端,然后再把序列化后的调用结果传回客户端。
    通过http完成简单的服务端的功能
    客户端
    1. 建立tcp/http连接
    2, 将对象序列化成json字符串 -- 序列化
    3. 发送json -- 调用成功后实际上你接收的是一个二级制的数据
    4. 等待服务器发送结果
    5. 将服务器返回的数据解析成对象 -- 反序列化
    
    服务端
    1. 监听端口
    2. 读取数据 -- 二级制的json数据
    3. 对数据进行反系列化对象
    4. 开始处理业务逻辑
    5. 将处理后的结果序列化为json二级制数据 -- 序列化
    6. 将数据返回
    
    反序列化和序列化是可以选择的,不一定采用json,xml,protobuf,msgpack
    
    func main() {
        //http://localhost:8000/add?a=1&b=2
        http.HandleFunc("/add", func(w http.ResponseWriter, r *http.Request) {
            //callID的问题,r.URL.PATH 数据传输协议 url的参数协议 网络传输协议http
            _ = r.ParseForm()
            fmt.Println("path: ", r.URL.Path)
            a, _ := strconv.Atoi(r.Form["a"][0])
            b, _ := strconv.Atoi(r.Form["b"][0])
            w.Header().Set("Content-Type", "application/json")
            data, _ := json.Marshal(map[string]int{
                "data": a + b,
            })
            _, _ = w.Write(data)
    
        })
    
        _ = http.ListenAndServe("127.0.0.1:8000", nil)
    }
    
    import (
        "encoding/json"
        "fmt"
        "github.com/kirinlabs/HttpRequest"
    )
    
    type ResponseDta struct {
        Data int `json:"Data"`
    }
    
    func add(a, b int) int {
        request := HttpRequest.NewRequest()
        response, _ := request.Get(fmt.Sprintf("http://127.0.0.1:8000/%s?a=%d&b=%d", "add", a, b))
        body, _ := response.Body()
        fmt.Println(string(body))
        responseDta := ResponseDta{}
        _ = json.Unmarshal(body, &responseDta)
        return responseDta.Data
    }
    func main() {
        add(2, 2)
    }
    
    go 内置rpc
    type HelloService struct {
    }
    
    func (s *HelloService) Hello(request string, reply *string) error {
        *reply = "hell0 " + request
        return nil
    }
    func main() {
        // 1实例化一个server
        listen, err := net.Listen("tcp", "127.0.0.1:1234")
        // 2注册处理逻辑 handler
        err = rpc.RegisterName("HelloService", &HelloService{})
        // 3启动服务
        accept, _ := listen.Accept()
        rpc.ServeConn(accept)
    
    }
    
    func main() {
        client, _ := rpc.Dial("tcp", "127.0.0.1:1234")
        var reply string
        err := client.Call("HelloService.Hello", "bobby", &reply)
        if err != nil {
            panic("")
        }
        fmt.Println(reply)
    }
    

    ....优化代码:封装和解耦:略

    protoc-gen-go 安装踩坑记录

    protoc-gen-go 安装踩坑记录

    --go_out: protoc-gen-go: plugins are not supported问题处理

    protoc-gen-go: plugins are not supported问题处理

    protobuf和json的对比
    syntax = "proto3";
    
    option go_package = "." ;
    
    message HelloRequest {
       string name = 1; // 1是编号
       int32 age = 2;
       repeated string course = 3;
    }
    
     protoc -I . helloworld.proto  --go_out=plugins=grpc:. 
    
    package main
    
    import (
        "encoding/json"
        "fmt"
        "github.com/golang/protobuf/proto"
        "rpcProject/DAY3/proto"
    )
    
    type Hello struct {
        Name    string   `json:"name"`
        Age     string   `json:"age"`
        Courses []string `json:"courses"`
    }
    
    func main() {
        request := __.HelloRequest{
            Name:   "Bobby",
            Age:    18,
            Course: []string{"go", "java", "scala"},
        }
        hello := Hello{
            Name:    "bobby",
            Age:     "18",
            Courses: []string{"go", "java", "scala"},
        }
        protomarshal, _ := proto.Marshal(&request)
        jsonmarshal, _ := json.Marshal(hello)
        newrequest := __.HelloRequest{}
        fmt.Println(len(protomarshal), len(jsonmarshal))
        proto.Unmarshal(protomarshal, &newrequest)
        fmt.Println(newrequest.Name, newrequest.Age, newrequest.Course)
    }
    
    为什么需要安装protoc和protoc-gen-go
    解决 "google.golang.org/grpc" 报红
    gopath路径
    grpc快速体验
    syntax = "proto3";
    option go_package = ".;proto";
    
    service Greeter{
        rpc SayHello(HelloRequest) returns (HelloReply);
    }
    
    message HelloRequest {
        string name = 1;
    }
    message HelloReply {
       string message = 2;
    }
    
    type Server struct {
    }
    
    func (s *Server) SayHello(ctx context.Context, re *proto.HelloRequest) (*proto.HelloReply, error) {
        return &proto.HelloReply{
            Message: "hello" + re.Name,
        }, nil
    }
    func main() {
        server := grpc.NewServer()
        proto.RegisterGreeterServer(server, &Server{})
        listen, _ := net.Listen("tcp", "0.0.0.0:8081")
        _ = server.Serve(listen)
    
    }
    
    func main() {
        conn, _ := grpc.Dial("0.0.0.0:8081", grpc.WithInsecure())
        defer conn.Close()
        client := proto.NewGreeterClient(conn)
        reply, _ := client.SayHello(context.Background(), &proto.HelloRequest{
            Name: "bobby",
        })
        fmt.Println(reply.Message)
    }
    
    grpc的流模式

    grpc的stream流模式

    option go_package的作用

    用于生成的.pb.go文件,在引用时和生成go包名时起作用,前一个参数用于指定生成文件的位置,后一个参数指定生成的 .go 文件的 package

    option go_package = "{out_path};out_go_package";
    
    proto文件中import另一个proto文件

    protobuf 导入另一文件夹下的proto

    疑问:这怎么解决
    我这里可能没装插件,参考:protobuf中使用import需要注意的点
    protobuf中的嵌套的message对象
    protobuf中的enum枚举类型
    protobuf中的map类型
    protobuf内置的timestamp类型

    Protobuf 教程

    grpc的metadata机制
    grpc的拦截器
    通过拦截器和metadata实现grpc的auth认证
    grpc的验证器
    grpc的状态码
    grpc中的错误处理
    grpc的超时机制
    protoc生成的go的源码里面有什么?

    相关文章

      网友评论

          本文标题:五. Go(Go protobuf)

          本文链接:https://www.haomeiwen.com/subject/iawfirtx.html