Go猜想录
大道至简,悟者天成
手搓 RPC 框架 -- #4 序列化

支持不同的序列化协议

  • Encode:将数据转化为字节
  • Decode:将字节转化为数据
  • Code:用一个字节来表达这种序列化协议,需要在客户端和服务端之间协商一致。例如用 1 来代表 JSON 序列化协议。
package serialize

type Serializer interface {
	Code() uint8
	Encode(val any) ([]byte, error)
	// Decode val 是一个结构体指针
	Decode(data []byte, val any) error
}

JSON 序列化协议

package json

import jsoniter "github.com/json-iterator/go"

type Serializer struct {
}

func (s *Serializer) Code() uint8 {
	return 1
}

func (s *Serializer) Encode(val any) ([]byte, error) {
	return jsoniter.Marshal(val)
}

func (s *Serializer) Decode(data []byte, val any) error {
	return jsoniter.Unmarshal(data, val)
}

Proto 序列化协议

package proto

import (
	"errors"

	"google.golang.org/protobuf/proto"
)

type Serializer struct {
}

func (s *Serializer) Code() uint8 {
	return 2
}

func (s *Serializer) Encode(val any) ([]byte, error) {
	msg, ok := val.(proto.Message)
	if !ok {
		return nil, errors.New("micro: val must be proto.Message")
	}
	return proto.Marshal(msg)
}

func (s *Serializer) Decode(data []byte, val any) error {
	msg, ok := val.(proto.Message)
	if !ok {
		return errors.New("micro: val must be proto.Message")
	}
	return proto.Unmarshal(data, msg)
}

客户端初始化

type Client struct {
	pool       pool.Pool
	serializer serialize.Serializer
}

type ClientOption func(client *Client)

func ClientWithSerializer(sl serialize.Serializer) ClientOption {
	return func(client *Client) {
		client.serializer = sl
	}
}

func NewClient(network, addr string, opts ...ClientOption) (*Client, error) {
	p, err := pool.NewChannelPool(
		&pool.Config{
			InitialCap:  1,
			MaxCap:      30,
			MaxIdle:     10,
			IdleTimeout: time.Minute,
			Factory: func() (interface{}, error) {
				return net.DialTimeout(network, addr, time.Second*3)
			},
			Close: func(i interface{}) error {
				return i.(net.Conn).Close()
			},
		},
	)
	if err != nil {
		return nil, err
	}

	c := &Client{
		pool:       p,
		serializer: &json.Serializer{},
	}

	for _, opt := range opts {
		opt(c)
	}

	return c, nil
}

服务端初始化

type Server struct {
	stubs       map[string]reflectionStub
	serializers map[uint8]serialize.Serializer
}

func NewServer() *Server {
	s := &Server{
		stubs:       make(map[string]reflectionStub, 16),
		serializers: make(map[uint8]serialize.Serializer, 4),
	}
	s.RegisterSerializer(&json.Serializer{})
	return s
}

func (s *Server) RegisterSerializer(sl serialize.Serializer) {
	s.serializers[sl.Code()] = sl
}

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。