golang 使用 protobuf

protobuf介绍这里不在叙述,可自行百度,有空再补.

安装 protobuf

使用release版本,编译安装

#下载

sudo apt-get install autoconf automake libtool curl make g++ unzip
git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git submodule update --init --recursive
./autogen.sh

#编译
 ./configure
make
make check

#安装
sudo make install
sudo ldconfig

# 检查
protoc -h

安装go插件

go get -u  -v github.com/golang/protobuf/proto
go get  -u -v github.com/golang/protobuf/protoc-gen-go

编译

 cd $GOPATH/src/github.com/golang/protobuf/protoc-gen-go/
 go install

此时会在$GOPATH/bin/生成二进制文件

ls  $GOPATH/bin/protoc-gen-go
/home/jinchunguang/go/bin/protoc-gen-go
protoc --go_out=plugins=grpc:. *.proto

➜  pro tree 
.
├── service.pb.go
└── service.proto

测试

golang 使用 protobuf_第1张图片
image.png
golang 使用 protobuf_第2张图片
image.png
golang 使用 protobuf_第3张图片
image.png
image.png

主要代码

contact_book.proto

syntax = "proto3";

package pro;

message Person {
    int32 id = 1;
    string name = 2;
    string  phone = 3;
}

message ContactBook {
    repeated Person persons = 1;
}

message_info.proto

syntax = "proto3";
package pro;

message Message{
    string message = 1;
    int32 length = 2;
}

main.go

package main

import (
    "fmt"
    "github.com/golang/protobuf/proto"
    "go-protobuf-demo/pro"
    "io/ioutil"
    "os"
)

func write() {

    book := &pro.ContactBook{}
    book.Persons = append(book.Persons, &pro.Person{Id: 1, Name: "小张", Phone: "130-1111-5678"});
    book.Persons = append(book.Persons, &pro.Person{Id: 2, Name: "小红", Phone: "131-2222-5678",});
    book.Persons = append(book.Persons, &pro.Person{Id: 3, Name: "小明", Phone: "172-3333-5678",});
    data, _ := proto.Marshal(book);
    fmt.Println("编码数据: ", data)

    ioutil.WriteFile("./cmd/book.data", data, os.ModePerm);
}

func read() {

    data, _ := ioutil.ReadFile("./cmd/book.data")
    book := &pro.ContactBook{};
    proto.Unmarshal(data, book);
    fmt.Println("解码数据: ", book.Persons)

    for _, v := range book.Persons {
        fmt.Println(v.Id, v.Name, v.Phone)
    }
}

func main() {
    write()
    read()
}

client.go

/**
 * @Author : jinchunguang
 * @Date : 19-11-6 下午4:52
 * @Project : go-protobuf-demo
 */
package main

import (
    "fmt"
    "github.com/golang/protobuf/proto"
    "go-protobuf-demo/pro"
    "net"
)

func main() {

    var err error
    var msg string

    // 收集消息
    fmt.Println("请输入短消息:")
    if _, err := fmt.Scanf("%s", &msg); err != nil {
        fmt.Printf("%s\n", err)
        return
    }

    // 编码数据
    user := &pro.Message{
        Message: msg,
        Length:  *proto.Int(len(msg)),
    }
    pbData, err := proto.Marshal(user)
    if err != nil {
        fmt.Println("proto marshal err ", err)
        return
    }

    // 连接server
    address := "localhost:6600"
    conn, err := net.Dial("tcp", address);
    defer conn.Close()
    if err != nil {
        fmt.Println("net dial err ", err)
        return
    }

    // 发送数据
    n, err := conn.Write(pbData)
    if err != nil {
        fmt.Println("net write err ", err)
        return
    }
    fmt.Println("conn write len:", n)

}

server.go

/**
 * @Author : jinchunguang
 * @Date : 19-11-6 下午4:52
 * @Project : go-protobuf-demo
 */
package main

import (
    "fmt"
    "github.com/golang/protobuf/proto"
    "go-protobuf-demo/pro"
    "io"
    "net"
)

func main() {

    address := "localhost:6600"
    listener, err := net.Listen("tcp", address)
    if err != nil {
        fmt.Errorf("listen err:", err)
    }
    fmt.Println("[START] Server listenner: ", address)
    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("conn err:", err)
            return
        }
        // 异步执行请求业务
        go processing(conn)
    }
}

func processing(conn net.Conn) {


    // 延迟关闭
    defer conn.Close()
    // 缓冲
    buf := make([]byte, 4096)
    for {
        len, err := conn.Read(buf)
        // 读取结束
        if err == io.EOF {
            return
        }

        if err != nil {
            fmt.Println("conn read err:", err)
            return
        }
        user := &pro.Message{}
        err = proto.Unmarshal(buf[:len], user)
        if err != nil {
            fmt.Println("proto unmarshal err:", err)
            return
        }

        fmt.Println("receive data:%v  ip:%v ", user.Message, conn.RemoteAddr())

    }
}

build.sh

#!/usr/bin/env bash

echo "生成GO文件"
cd pro
protoc --go_out=plugins=grpc:. *.proto

# 构建 file 执行文件
echo "生成执行文件"
cd ..
go build -o cmd/file file/main.go
go build -o cmd/pb_server cs/server/server.go
go build -o cmd/pb_client cs/client/client.go

未完待续.

你可能感兴趣的:(golang 使用 protobuf)