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开发的小栗子完成。

posted @ 2020-05-16 23:27  cnlihao  阅读(748)  评论(0编辑  收藏  举报