zoukankan      html  css  js  c++  java
  • goland下tarsgo使用protobuf开发(一)

    首先,我们创建一个空的项目目录

    然后,打开goland一次设置配置。
    本次使用golang 1.14版本。

    使用modules模式开发。

    第一步,初始化项目

    go mod init protoTest
    

    第二步,下载tarsgo包、proto、protoc-gen-go

    go get github.com/TarsCloud/TarsGo/tars
    go get  github.com/golang/protobuf/proto
    go get  github.com/golang/protobuf/protoc-gen-go
    

    第三步,为protoc-gen-go添加tarsrpc插件
    不会生成protoc-gen-go的,查看:https://www.cnblogs.com/cnlihao/p/12903160.html

    第四步,我们创建一个简单的helloworld.proto和放置其生成文件的目录proto/helloworld

    syntax = "proto3";
    package helloworld;
    
    // The greeting service definition.
    service Greeter {
      // Sends a greeting
      rpc SayHello (HelloRequest) returns (HelloReply) {}
    }
    
    // The request message containing the user's name.
    message HelloRequest {
      string name = 1;
    }
    
    // The response message containing the greetings
    message HelloReply {
      string message = 1;
    }
    

    第五步,使用命令生成文件helloworld.pb.go

    protoc --go_out=plugins=tarsrpc:./proto/helloworld helloworld.proto
    #其中plugins后面是我们自定义的tarsrpc协议,再后面是生成文件放置的目录
    

    生成的helloworld.pb.go如下:

    // Code generated by protoc-gen-go. DO NOT EDIT.
    // source: helloworld.proto
    
    package helloworld
    
    import (
    	context "context"
    	fmt "fmt"
    	tars "github.com/TarsCloud/TarsGo/tars"
    	model "github.com/TarsCloud/TarsGo/tars/model"
    	requestf "github.com/TarsCloud/TarsGo/tars/protocol/res/requestf"
    	current "github.com/TarsCloud/TarsGo/tars/util/current"
    	tools "github.com/TarsCloud/TarsGo/tars/util/tools"
    	proto "github.com/golang/protobuf/proto"
    	math "math"
    )
    
    // Reference imports to suppress errors if they are not otherwise used.
    var _ = proto.Marshal
    var _ = fmt.Errorf
    var _ = math.Inf
    
    // This is a compile-time assertion to ensure that this generated file
    // is compatible with the proto package it is being compiled against.
    // A compilation error at this line likely means your copy of the
    // proto package needs to be updated.
    const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
    
    // The request message containing the user's name.
    type HelloRequest struct {
    	Name                 string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
    	XXX_NoUnkeyedLiteral struct{} `json:"-"`
    	XXX_unrecognized     []byte   `json:"-"`
    	XXX_sizecache        int32    `json:"-"`
    }
    
    func (m *HelloRequest) Reset()         { *m = HelloRequest{} }
    func (m *HelloRequest) String() string { return proto.CompactTextString(m) }
    func (*HelloRequest) ProtoMessage()    {}
    func (*HelloRequest) Descriptor() ([]byte, []int) {
    	return fileDescriptor_17b8c58d586b62f2, []int{0}
    }
    
    func (m *HelloRequest) XXX_Unmarshal(b []byte) error {
    	return xxx_messageInfo_HelloRequest.Unmarshal(m, b)
    }
    func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
    	return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic)
    }
    func (m *HelloRequest) XXX_Merge(src proto.Message) {
    	xxx_messageInfo_HelloRequest.Merge(m, src)
    }
    func (m *HelloRequest) XXX_Size() int {
    	return xxx_messageInfo_HelloRequest.Size(m)
    }
    func (m *HelloRequest) XXX_DiscardUnknown() {
    	xxx_messageInfo_HelloRequest.DiscardUnknown(m)
    }
    
    var xxx_messageInfo_HelloRequest proto.InternalMessageInfo
    
    func (m *HelloRequest) GetName() string {
    	if m != nil {
    		return m.Name
    	}
    	return ""
    }
    
    // The response message containing the greetings
    type HelloReply struct {
    	Message              string   `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
    	XXX_NoUnkeyedLiteral struct{} `json:"-"`
    	XXX_unrecognized     []byte   `json:"-"`
    	XXX_sizecache        int32    `json:"-"`
    }
    
    func (m *HelloReply) Reset()         { *m = HelloReply{} }
    func (m *HelloReply) String() string { return proto.CompactTextString(m) }
    func (*HelloReply) ProtoMessage()    {}
    func (*HelloReply) Descriptor() ([]byte, []int) {
    	return fileDescriptor_17b8c58d586b62f2, []int{1}
    }
    
    func (m *HelloReply) XXX_Unmarshal(b []byte) error {
    	return xxx_messageInfo_HelloReply.Unmarshal(m, b)
    }
    func (m *HelloReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
    	return xxx_messageInfo_HelloReply.Marshal(b, m, deterministic)
    }
    func (m *HelloReply) XXX_Merge(src proto.Message) {
    	xxx_messageInfo_HelloReply.Merge(m, src)
    }
    func (m *HelloReply) XXX_Size() int {
    	return xxx_messageInfo_HelloReply.Size(m)
    }
    func (m *HelloReply) XXX_DiscardUnknown() {
    	xxx_messageInfo_HelloReply.DiscardUnknown(m)
    }
    
    var xxx_messageInfo_HelloReply proto.InternalMessageInfo
    
    func (m *HelloReply) GetMessage() string {
    	if m != nil {
    		return m.Message
    	}
    	return ""
    }
    
    func init() {
    	proto.RegisterType((*HelloRequest)(nil), "helloworld.HelloRequest")
    	proto.RegisterType((*HelloReply)(nil), "helloworld.HelloReply")
    }
    
    func init() {
    	proto.RegisterFile("helloworld.proto", fileDescriptor_17b8c58d586b62f2)
    }
    
    var fileDescriptor_17b8c58d586b62f2 = []byte{
    	// 141 bytes of a gzipped FileDescriptorProto
    	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9,
    	0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0x88,
    	0x28, 0x29, 0x71, 0xf1, 0x78, 0x80, 0x78, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42,
    	0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0xb6, 0x92,
    	0x1a, 0x17, 0x17, 0x54, 0x4d, 0x41, 0x4e, 0xa5, 0x90, 0x04, 0x17, 0x7b, 0x6e, 0x6a, 0x71, 0x71,
    	0x62, 0x3a, 0x4c, 0x11, 0x8c, 0x6b, 0xe4, 0xc9, 0xc5, 0xee, 0x5e, 0x94, 0x9a, 0x5a, 0x92, 0x5a,
    	0x24, 0x64, 0xc7, 0xc5, 0x11, 0x9c, 0x58, 0x09, 0xd6, 0x25, 0x24, 0xa1, 0x87, 0xe4, 0x02, 0x64,
    	0xcb, 0xa4, 0xc4, 0xb0, 0xc8, 0x14, 0xe4, 0x54, 0x2a, 0x31, 0x24, 0xb1, 0x81, 0x5d, 0x6a, 0x0c,
    	0x08, 0x00, 0x00, 0xff, 0xff, 0xd6, 0x53, 0x4e, 0xf7, 0xbd, 0x00, 0x00, 0x00,
    }
    
    // This following code was generated by tarsrpc
    // Gernerated from helloworld.proto
    type Greeter struct {
    	s model.Servant
    }
    
    //SetServant is required by the servant interface.
    func (obj *Greeter) SetServant(s model.Servant) {
    	obj.s = s
    }
    
    //AddServant is required by the servant interface
    func (obj *Greeter) AddServant(imp impGreeter, objStr string) {
    	tars.AddServant(obj, imp, objStr)
    }
    
    ////AddServant adds servant  for the service with context
    func (obj *Greeter) AddServantWithContext(imp impGreeterWithContext, objStr string) {
    	tars.AddServantWithContext(obj, imp, objStr)
    }
    
    //TarsSetTimeout is required by the servant interface. t is the timeout in ms.
    func (obj *Greeter) TarsSetTimeout(t int) {
    	obj.s.TarsSetTimeout(t)
    }
    
    //TarsSetProtocol is required by the servant interface. t is the protocol.
    func (obj *Greeter) TarsSetProtocol(p model.Protocol) {
    	obj.s.TarsSetProtocol(p)
    }
    
    type impGreeter interface {
    	SayHello(input HelloRequest) (output HelloReply, err error)
    }
    
    type impGreeterWithContext interface {
    	SayHello(ctx context.Context, input HelloRequest) (output HelloReply, err error)
    }
    
    //Dispatch is used to call the user implement of the defined method.
    func (obj *Greeter) Dispatch(ctx context.Context, val interface{}, req *requestf.RequestPacket, resp *requestf.ResponsePacket, withContext bool) (err error) {
    	input := tools.Int8ToByte(req.SBuffer)
    	var output []byte
    	funcName := req.SFuncName
    	switch funcName {
    
    	case "SayHello":
    		inputDefine := HelloRequest{}
    		if err = proto.Unmarshal(input, &inputDefine); err != nil {
    			return err
    		}
    		var res HelloReply
    		if withContext == false {
    			imp := val.(impGreeter)
    			res, err = imp.SayHello(inputDefine)
    			if err != nil {
    				return err
    			}
    		} else {
    			imp := val.(impGreeterWithContext)
    			res, err = imp.SayHello(ctx, inputDefine)
    			if err != nil {
    				return err
    			}
    		}
    		output, err = proto.Marshal(&res)
    		if err != nil {
    			return err
    		}
    
    	default:
    		return fmt.Errorf("func mismatch")
    	}
    	var _status map[string]string
    	s, ok := current.GetResponseStatus(ctx)
    	if ok && s != nil {
    		_status = s
    	}
    	var _context map[string]string
    	c, ok := current.GetResponseContext(ctx)
    	if ok && c != nil {
    		_context = c
    	}
    	*resp = requestf.ResponsePacket{
    		IVersion:     1,
    		CPacketType:  0,
    		IRequestId:   req.IRequestId,
    		IMessageType: 0,
    		IRet:         0,
    		SBuffer:      tools.ByteToInt8(output),
    		Status:       _status,
    		SResultDesc:  "",
    		Context:      _context,
    	}
    	return nil
    }
    
    // SayHello is client rpc method as defined
    func (obj *Greeter) SayHello(input HelloRequest, _opt ...map[string]string) (output HelloReply, err error) {
    	ctx := context.Background()
    	return obj.SayHelloWithContext(ctx, input, _opt...)
    }
    
    // SayHelloWithContext is client rpc method as defined
    func (obj *Greeter) SayHelloWithContext(ctx context.Context, input HelloRequest, _opt ...map[string]string) (output HelloReply, err error) {
    	var inputMarshal []byte
    	inputMarshal, err = proto.Marshal(&input)
    	if err != nil {
    		return output, err
    	}
    
    	var _status map[string]string
    	var _context map[string]string
    	if len(_opt) == 1 {
    		_context = _opt[0]
    	} else if len(_opt) == 2 {
    		_context = _opt[0]
    		_status = _opt[1]
    	}
    
    	resp := new(requestf.ResponsePacket)
    
    	err = obj.s.Tars_invoke(ctx, 0, "SayHello", inputMarshal, _status, _context, resp)
    	if err != nil {
    		return output, err
    	}
    	if err = proto.Unmarshal(tools.Int8ToByte(resp.SBuffer), &output); err != nil {
    		return output, err
    	}
    
    	if len(_opt) == 1 {
    		for k := range _context {
    			delete(_context, k)
    		}
    		for k, v := range resp.Context {
    			_context[k] = v
    		}
    	} else if len(_opt) == 2 {
    		for k := range _context {
    			delete(_context, k)
    		}
    		for k, v := range resp.Context {
    			_context[k] = v
    		}
    		for k := range _status {
    			delete(_status, k)
    		}
    		for k, v := range resp.Status {
    			_status[k] = v
    		}
    	}
    
    	return output, nil
    }
    
    

    第六步,我们在项目下创建一个服务端和客户端,完整目录如下:

    客户端:

    package main
    
    import (
    	"fmt"
    	"github.com/TarsCloud/TarsGo/tars"
    	"protoTest/proto/helloworld"
    )
    
    func main() {
    	comm := tars.NewCommunicator()
    	obj := fmt.Sprintf("StressTest.HelloPbServer.GreeterTestObj@tcp -h 127.0.0.1  -p 10014  -t 60000")
    	app := new(helloworld.Greeter)
    	comm.StringToProxy(obj, app)
    	input := helloworld.HelloRequest{Name: "sandyskies"}
    	output, err := app.SayHello(input)
    	if err != nil {
    		fmt.Println("err: ", err)
    	}
    	fmt.Println("result is:", output.Message)
    }
    

    服务端:

    package main
    
    import (
    	"github.com/TarsCloud/TarsGo/tars"
    	"protoTest/proto/helloworld"
    )
    
    type GreeterImp  struct {
    }
    
    func (imp *GreeterImp) SayHello(input helloworld.HelloRequest)(output helloworld.HelloReply, err error) {
    	output.Message = "hello" +  input.GetName()
    	return output, nil
    }
    
    func main() { //Init servant
    
    	imp := new(GreeterImp)                                    //New Imp
    	app := new(helloworld.Greeter)                            //New init the A JCE
    	cfg := tars.GetServerConfig()                              //Get Config File Object
    	app.AddServant(imp, cfg.App+"."+cfg.Server+".GreeterTestObj") //Register Servant
    	tars.Run()
    }
    
    

    最后,tarsgo基于protobuf开发的小栗子完成。

  • 相关阅读:
    CF1137C Museums Tour(tarjan+DP)
    Educational Codeforces Round 65 (Rated for Div. 2)
    Codeforces Round #559(Div.1)
    委托
    类库
    is 和 as 运算符
    面向对象 接口
    抽象类
    面向对象 多态
    访问修饰符 程序集 静态方法
  • 原文地址:https://www.cnblogs.com/cnlihao/p/12902844.html
Copyright © 2011-2022 走看看