Documentation ¶
Index ¶
- Constants
- Variables
- func Auth(fn AuthorizationFunc) error
- func Close() error
- func GetListenedAddress() string
- func NewDirectHTTPRPCClient(c *Client, clientCodecFunc ClientCodecFunc, network, address string, ...) (*rpc.Client, error)
- func NewDirectRPCClient(c *Client, clientCodecFunc ClientCodecFunc, network, address string, ...) (*rpc.Client, error)
- func RegisterName(name string, service interface{}, metadata ...string)
- func Serve(n, address string)
- func ServeByHTTP(ln net.Listener, rpcPath, debugPath string)
- func ServeListener(ln net.Listener)
- func ServeTLS(n, address string, config *tls.Config)
- func SetServerCodecFunc(fn ServerCodecFunc)
- func Start(n, address string)
- func StartTLS(n, address string, config *tls.Config)
- type AuthorizationAndServiceMethod
- type AuthorizationClientPlugin
- type AuthorizationFunc
- type AuthorizationServerPlugin
- type Client
- type ClientCodecFunc
- type ClientPluginContainer
- func (p *ClientPluginContainer) Add(plugin IPlugin) error
- func (p *ClientPluginContainer) DoPostReadResponseBody(body interface{}) error
- func (p *ClientPluginContainer) DoPostReadResponseHeader(r *rpc.Response) error
- func (p *ClientPluginContainer) DoPostWriteRequest(r *rpc.Request, body interface{}) error
- func (p *ClientPluginContainer) DoPreReadResponseBody(body interface{}) error
- func (p *ClientPluginContainer) DoPreReadResponseHeader(r *rpc.Response) error
- func (p *ClientPluginContainer) DoPreWriteRequest(r *rpc.Request, body interface{}) error
- func (p *ClientPluginContainer) GetAll() []IPlugin
- func (p *ClientPluginContainer) GetByName(pluginName string) IPlugin
- func (p *ClientPluginContainer) GetDescription(plugin IPlugin) string
- func (p *ClientPluginContainer) GetName(plugin IPlugin) string
- func (p *ClientPluginContainer) Remove(pluginName string) error
- type ClientSelector
- type DirectClientSelector
- func (s *DirectClientSelector) AllClients(clientCodecFunc ClientCodecFunc) []*rpc.Client
- func (s *DirectClientSelector) Select(clientCodecFunc ClientCodecFunc, options ...interface{}) (*rpc.Client, error)
- func (s *DirectClientSelector) SetClient(c *Client)
- func (s *DirectClientSelector) SetSelectMode(sm SelectMode)
- type FailMode
- type IClientPluginContainer
- type IPlugin
- type IPostConnAcceptPlugin
- type IPostReadRequestBodyPlugin
- type IPostReadRequestHeaderPlugin
- type IPostReadResponseBodyPlugin
- type IPostReadResponseHeaderPlugin
- type IPostWriteRequestPlugin
- type IPostWriteResponsePlugin
- type IPreReadRequestBodyPlugin
- type IPreReadRequestHeaderPlugin
- type IPreReadResponseBodyPlugin
- type IPreReadResponseHeaderPlugin
- type IPreWriteRequestPlugin
- type IPreWriteResponsePlugin
- type IRegisterPlugin
- type IServerCodecPlugin
- type IServerPluginContainer
- type MultiError
- type RPCError
- type SelectMode
- type Server
- func (s *Server) Address() string
- func (s *Server) Auth(fn AuthorizationFunc) error
- func (s *Server) Close() error
- func (s *Server) RegisterName(name string, service interface{}, metadata ...string)
- func (s *Server) Serve(network, address string)
- func (s *Server) ServeByHTTP(ln net.Listener, rpcPath string)
- func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request)
- func (s *Server) ServeListener(ln net.Listener)
- func (s *Server) ServeTLS(network, address string, config *tls.Config)
- func (s *Server) Start(network, address string)
- func (s *Server) StartTLS(network, address string, config *tls.Config)
- type ServerCodecFunc
- type ServerPluginContainer
- func (p *ServerPluginContainer) Add(plugin IPlugin) error
- func (p *ServerPluginContainer) DoPostConnAccept(conn net.Conn) bool
- func (p *ServerPluginContainer) DoPostReadRequestBody(body interface{}) error
- func (p *ServerPluginContainer) DoPostReadRequestHeader(r *rpc.Request) error
- func (p *ServerPluginContainer) DoPostWriteResponse(resp *rpc.Response, body interface{}) error
- func (p *ServerPluginContainer) DoPreReadRequestBody(body interface{}) error
- func (p *ServerPluginContainer) DoPreReadRequestHeader(r *rpc.Request) error
- func (p *ServerPluginContainer) DoPreWriteResponse(resp *rpc.Response, body interface{}) error
- func (p *ServerPluginContainer) DoRegister(name string, rcvr interface{}, metadata ...string) error
- func (p *ServerPluginContainer) GetAll() []IPlugin
- func (p *ServerPluginContainer) GetByName(pluginName string) IPlugin
- func (p *ServerPluginContainer) GetDescription(plugin IPlugin) string
- func (p *ServerPluginContainer) GetName(plugin IPlugin) string
- func (p *ServerPluginContainer) Remove(pluginName string) error
Constants ¶
const (
//DefaultRPCPath is the defaut HTTP RPC PATH
DefaultRPCPath = "/_goRPC_"
)
Variables ¶
var ( // ErrPluginAlreadyExists returns an error with message: 'Cannot activate the same plugin again, plugin '+plugin name[+plugin description]' is already exists' ErrPluginAlreadyExists = NewRPCError("Cannot use the same plugin again, '%s[%s]' is already exists") // ErrPluginActivate returns an error with message: 'While trying to activate plugin '+plugin name'. Trace: +specific error' ErrPluginActivate = NewRPCError("While trying to activate plugin '%s'. Trace: %s") // ErrPluginRemoveNoPlugins returns an error with message: 'No plugins are registed yet, you cannot remove a plugin from an empty list!' ErrPluginRemoveNoPlugins = NewRPCError("No plugins are registed yet, you cannot remove a plugin from an empty list!") // ErrPluginRemoveEmptyName returns an error with message: 'Plugin with an empty name cannot be removed' ErrPluginRemoveEmptyName = NewRPCError("Plugin with an empty name cannot be removed") // ErrPluginRemoveNotFound returns an error with message: 'Cannot remove a plugin which doesn't exists' ErrPluginRemoveNotFound = NewRPCError("Cannot remove a plugin which doesn't exists") )
Functions ¶
func GetListenedAddress ¶
func GetListenedAddress() string
GetListenedAddress return the listening address.
func NewDirectHTTPRPCClient ¶
func NewDirectHTTPRPCClient(c *Client, clientCodecFunc ClientCodecFunc, network, address string, path string, timeout time.Duration) (*rpc.Client, error)
NewDirectHTTPRPCClient creates a rpc http client
func NewDirectRPCClient ¶
func NewDirectRPCClient(c *Client, clientCodecFunc ClientCodecFunc, network, address string, timeout time.Duration) (*rpc.Client, error)
NewDirectRPCClient creates a rpc client
func RegisterName ¶
RegisterName publishes in the server the set of methods .
func Serve ¶
func Serve(n, address string)
Serve starts and listens RCP requests. It is blocked until receiving connectings from clients.
func ServeByHTTP ¶
ServeByHTTP implements RPC via HTTP
func ServeTLS ¶
ServeTLS starts and listens RCP requests. It is blocked until receiving connectings from clients.
func SetServerCodecFunc ¶
func SetServerCodecFunc(fn ServerCodecFunc)
SetServerCodecFunc sets a ServerCodecFunc
Types ¶
type AuthorizationAndServiceMethod ¶
type AuthorizationAndServiceMethod struct { Authorization string // Authorization ServiceMethod string // real ServiceMethod name Tag string // extra tag for Authorization }
AuthorizationAndServiceMethod represents Authorization header and ServiceMethod.
func (*AuthorizationAndServiceMethod) String ¶ added in v1.1.1
func (aasm *AuthorizationAndServiceMethod) String() string
type AuthorizationClientPlugin ¶
type AuthorizationClientPlugin struct {
AuthorizationAndServiceMethod *AuthorizationAndServiceMethod
}
AuthorizationClientPlugin is used to set Authorization info at client side.
func NewAuthorizationClientPlugin ¶
func NewAuthorizationClientPlugin(authorization, tag string) *AuthorizationClientPlugin
NewAuthorizationClientPlugin creates a AuthorizationClientPlugin with authorization header and tag
func (*AuthorizationClientPlugin) Description ¶
func (plugin *AuthorizationClientPlugin) Description() string
Description return description of this plugin.
func (*AuthorizationClientPlugin) Name ¶
func (plugin *AuthorizationClientPlugin) Name() string
Name return name of this plugin.
func (*AuthorizationClientPlugin) PreWriteRequest ¶
func (plugin *AuthorizationClientPlugin) PreWriteRequest(r *rpc.Request, body interface{}) error
PreWriteRequest adds Authorization info in requests
type AuthorizationFunc ¶
type AuthorizationFunc func(p *AuthorizationAndServiceMethod) error
AuthorizationFunc defines a method type which handles Authorization info
type AuthorizationServerPlugin ¶
type AuthorizationServerPlugin struct {
AuthorizationFunc AuthorizationFunc
}
AuthorizationServerPlugin is used to authorize clients.
func (*AuthorizationServerPlugin) Description ¶
func (plugin *AuthorizationServerPlugin) Description() string
Description return description of this plugin.
func (*AuthorizationServerPlugin) Name ¶
func (plugin *AuthorizationServerPlugin) Name() string
Name return name of this plugin.
func (*AuthorizationServerPlugin) PostReadRequestHeader ¶
func (plugin *AuthorizationServerPlugin) PostReadRequestHeader(r *rpc.Request) (err error)
PostReadRequestHeader extracts Authorization header from ServiceMethod field.
type Client ¶
type Client struct { ClientSelector ClientSelector ClientCodecFunc ClientCodecFunc PluginContainer IClientPluginContainer FailMode FailMode TLSConfig *tls.Config Retries int //Timeout sets deadline for underlying net.Conns Timeout time.Duration //Timeout sets readdeadline for underlying net.Conns ReadTimeout time.Duration //Timeout sets writedeadline for underlying net.Conns WriteTimeout time.Duration }
Client represents a RPC client.
func (*Client) Call ¶
Call invokes the named function, waits for it to complete, and returns its error status.
func (*Client) Go ¶
func (c *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *rpc.Call) *rpc.Call
Go invokes the function asynchronously. It returns the Call structure representing the invocation. The done channel will signal when the call is complete by returning the same Call object. If done is nil, Go will allocate a new channel. If non-nil, done must be buffered or Go will deliberately crash.
type ClientCodecFunc ¶
type ClientCodecFunc func(conn io.ReadWriteCloser) rpc.ClientCodec
ClientCodecFunc is used to create a rpc.ClientCodecFunc from net.Conn.
type ClientPluginContainer ¶
type ClientPluginContainer struct {
// contains filtered or unexported fields
}
ClientPluginContainer implements IPluginContainer interface.
func (*ClientPluginContainer) Add ¶
func (p *ClientPluginContainer) Add(plugin IPlugin) error
Add adds a plugin.
func (*ClientPluginContainer) DoPostReadResponseBody ¶
func (p *ClientPluginContainer) DoPostReadResponseBody(body interface{}) error
DoPostReadResponseBody invokes DoPostReadResponseBody plugin.
func (*ClientPluginContainer) DoPostReadResponseHeader ¶
func (p *ClientPluginContainer) DoPostReadResponseHeader(r *rpc.Response) error
DoPostReadResponseHeader invokes DoPostReadResponseHeader plugin.
func (*ClientPluginContainer) DoPostWriteRequest ¶
func (p *ClientPluginContainer) DoPostWriteRequest(r *rpc.Request, body interface{}) error
DoPostWriteRequest invokes DoPostWriteRequest plugin.
func (*ClientPluginContainer) DoPreReadResponseBody ¶
func (p *ClientPluginContainer) DoPreReadResponseBody(body interface{}) error
DoPreReadResponseBody invokes DoPreReadResponseBody plugin.
func (*ClientPluginContainer) DoPreReadResponseHeader ¶
func (p *ClientPluginContainer) DoPreReadResponseHeader(r *rpc.Response) error
DoPreReadResponseHeader invokes DoPreReadResponseHeader plugin.
func (*ClientPluginContainer) DoPreWriteRequest ¶
func (p *ClientPluginContainer) DoPreWriteRequest(r *rpc.Request, body interface{}) error
DoPreWriteRequest invokes DoPreWriteRequest plugin.
func (*ClientPluginContainer) GetAll ¶
func (p *ClientPluginContainer) GetAll() []IPlugin
GetAll returns all activated plugins
func (*ClientPluginContainer) GetByName ¶
func (p *ClientPluginContainer) GetByName(pluginName string) IPlugin
GetByName returns a plugin instance by it's name
func (*ClientPluginContainer) GetDescription ¶
func (p *ClientPluginContainer) GetDescription(plugin IPlugin) string
GetDescription returns the name of a plugin, if no GetDescription() implemented it returns an empty string ""
func (*ClientPluginContainer) GetName ¶
func (p *ClientPluginContainer) GetName(plugin IPlugin) string
GetName returns the name of a plugin, if no GetName() implemented it returns an empty string ""
func (*ClientPluginContainer) Remove ¶
func (p *ClientPluginContainer) Remove(pluginName string) error
Remove removes a plugin by it's name.
type ClientSelector ¶
type ClientSelector interface { //Select returns a new client and it also update current client Select(clientCodecFunc ClientCodecFunc, options ...interface{}) (*rpc.Client, error) //SetClient set current client SetClient(*Client) SetSelectMode(SelectMode) //AllClients returns all Clients AllClients(clientCodecFunc ClientCodecFunc) []*rpc.Client }
ClientSelector defines an interface to create a rpc.Client from cluster or standalone.
type DirectClientSelector ¶
type DirectClientSelector struct {
Network, Address string
DialTimeout time.Duration
Client *Client
// contains filtered or unexported fields
}
DirectClientSelector is used to a direct rpc server. It don't select a node from service cluster but a specific rpc server.
func (*DirectClientSelector) AllClients ¶
func (s *DirectClientSelector) AllClients(clientCodecFunc ClientCodecFunc) []*rpc.Client
AllClients returns rpc.Clients to all servers
func (*DirectClientSelector) Select ¶
func (s *DirectClientSelector) Select(clientCodecFunc ClientCodecFunc, options ...interface{}) (*rpc.Client, error)
Select returns a rpc client.
func (*DirectClientSelector) SetClient ¶
func (s *DirectClientSelector) SetClient(c *Client)
SetClient sets the unique client.
func (*DirectClientSelector) SetSelectMode ¶
func (s *DirectClientSelector) SetSelectMode(sm SelectMode)
SetSelectMode is meaningless for DirectClientSelector because there is only one client.
type FailMode ¶
type FailMode int
FailMode is a feature to decide client actions when clients fail to invoke services
const ( //Failover selects another server automaticaly Failover FailMode = iota //Failfast returns error immediately Failfast //Failtry use current client again Failtry //Broadcast sends requests to all servers and Success only when all servers return OK Broadcast //Forking sends requests to all servers and Success once one server returns OK Forking )
type IClientPluginContainer ¶
type IClientPluginContainer interface { Add(plugin IPlugin) error Remove(pluginName string) error GetName(plugin IPlugin) string GetDescription(plugin IPlugin) string GetByName(pluginName string) IPlugin GetAll() []IPlugin DoPreReadResponseHeader(*rpc.Response) error DoPostReadResponseHeader(*rpc.Response) error DoPreReadResponseBody(interface{}) error DoPostReadResponseBody(interface{}) error DoPreWriteRequest(*rpc.Request, interface{}) error DoPostWriteRequest(*rpc.Request, interface{}) error }
IClientPluginContainer represents a plugin container that defines all methods to manage plugins. And it also defines all extension points.
type IPostConnAcceptPlugin ¶
IPostConnAcceptPlugin represents connection accept plugin. if returns false, it means subsequent IPostConnAcceptPlugins should not contiune to handle this conn and this conn has been closed.
type IPostReadRequestBodyPlugin ¶
type IPostReadRequestBodyPlugin interface {
PostReadRequestBody(body interface{}) error
}
IPostReadRequestBodyPlugin represents .
type IPostReadRequestHeaderPlugin ¶
IPostReadRequestHeaderPlugin represents .
type IPostReadResponseBodyPlugin ¶
type IPostReadResponseBodyPlugin interface {
PostReadResponseBody(interface{}) error
}
IPostReadResponseBodyPlugin represents .
type IPostReadResponseHeaderPlugin ¶
IPostReadResponseHeaderPlugin represents .
type IPostWriteRequestPlugin ¶
IPostWriteRequestPlugin represents .
type IPostWriteResponsePlugin ¶
IPostWriteResponsePlugin represents .
type IPreReadRequestBodyPlugin ¶
type IPreReadRequestBodyPlugin interface {
PreReadRequestBody(body interface{}) error
}
IPreReadRequestBodyPlugin represents .
type IPreReadRequestHeaderPlugin ¶
IPreReadRequestHeaderPlugin represents .
type IPreReadResponseBodyPlugin ¶
type IPreReadResponseBodyPlugin interface {
PreReadResponseBody(interface{}) error
}
IPreReadResponseBodyPlugin represents .
type IPreReadResponseHeaderPlugin ¶
IPreReadResponseHeaderPlugin represents .
type IPreWriteRequestPlugin ¶
IPreWriteRequestPlugin represents .
type IPreWriteResponsePlugin ¶
IPreWriteResponsePlugin represents .
type IRegisterPlugin ¶
type IRegisterPlugin interface {
Register(name string, rcvr interface{}, metadata ...string) error
}
IRegisterPlugin represents register plugin.
type IServerCodecPlugin ¶
type IServerCodecPlugin interface { IPreReadRequestHeaderPlugin IPostReadRequestHeaderPlugin IPreReadRequestBodyPlugin IPostReadRequestBodyPlugin IPreWriteResponsePlugin IPostWriteResponsePlugin }
IServerCodecPlugin represents .
type IServerPluginContainer ¶
type IServerPluginContainer interface { Add(plugin IPlugin) error Remove(pluginName string) error GetName(plugin IPlugin) string GetDescription(plugin IPlugin) string GetByName(pluginName string) IPlugin GetAll() []IPlugin DoRegister(name string, rcvr interface{}, metadata ...string) error DoPostConnAccept(net.Conn) bool DoPreReadRequestHeader(r *rpc.Request) error DoPostReadRequestHeader(r *rpc.Request) error DoPreReadRequestBody(body interface{}) error DoPostReadRequestBody(body interface{}) error DoPreWriteResponse(*rpc.Response, interface{}) error DoPostWriteResponse(*rpc.Response, interface{}) error }
IServerPluginContainer represents a plugin container that defines all methods to manage plugins. And it also defines all extension points.
func GetPluginContainer ¶
func GetPluginContainer() IServerPluginContainer
GetPluginContainer get PluginContainer of default server.
type MultiError ¶
type MultiError struct {
Errors []error
}
MultiError holds multiple errors
func NewMultiError ¶
func NewMultiError(errors []error) *MultiError
NewMultiError creates and returns an Error with error splice
func (*MultiError) Error ¶
func (e *MultiError) Error() string
Error returns the message of the actual error
type RPCError ¶
type RPCError struct {
// contains filtered or unexported fields
}
RPCError holds the error
func NewRPCError ¶
NewRPCError creates and returns an Error with a message
func (*RPCError) Panicf ¶
func (e *RPCError) Panicf(args ...interface{})
Panicf output the formatted message and after panics
type SelectMode ¶
type SelectMode int
SelectMode defines the algorithm of selecting a services from cluster
const ( //RandomSelect is selecting randomly RandomSelect SelectMode = iota //RoundRobin is selecting by round robin RoundRobin //WeightedRoundRobin is selecting by weighted round robin WeightedRoundRobin //WeightedICMP is selecting by weighted Ping time WeightedICMP //ConsistentHash is selecting by hashing ConsistentHash //Closest is selecting the closest server Closest )
func (SelectMode) String ¶
func (s SelectMode) String() string
type Server ¶
type Server struct { ServerCodecFunc ServerCodecFunc //PluginContainer must be configured before starting and Register plugins must be configured before invoking RegisterName method PluginContainer IServerPluginContainer //Metadata describes extra info about this service, for example, weight, active status Metadata string Timeout time.Duration ReadTimeout time.Duration WriteTimeout time.Duration // contains filtered or unexported fields }
Server represents a RPC Server.
func (*Server) Auth ¶
func (s *Server) Auth(fn AuthorizationFunc) error
Auth sets authorization function
func (*Server) RegisterName ¶
RegisterName publishes in the server the set of methods of the receiver value that satisfy the following conditions:
- exported method of exported type
- two arguments, both of exported type
- the second argument is a pointer
- one return value, of type error
It returns an error if the receiver is not an exported type or has no suitable methods. It also logs the error using package log. The client accesses each method using a string of the form "Type.Method", where Type is the receiver's concrete type.
func (*Server) Serve ¶
Serve starts and listens RCP requests. It is blocked until receiving connectings from clients.
func (*Server) ServeByHTTP ¶
ServeByHTTP starts
func (*Server) ServeHTTP ¶
func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request)
ServeHTTP implements net handler interface
func (*Server) ServeTLS ¶
ServeTLS starts and listens RCP requests. It is blocked until receiving connectings from clients.
type ServerCodecFunc ¶
type ServerCodecFunc func(conn io.ReadWriteCloser) rpc.ServerCodec
ServerCodecFunc is used to create a rpc.ServerCodec from net.Conn.
type ServerPluginContainer ¶
type ServerPluginContainer struct {
// contains filtered or unexported fields
}
ServerPluginContainer implements IPluginContainer interface.
func (*ServerPluginContainer) Add ¶
func (p *ServerPluginContainer) Add(plugin IPlugin) error
Add adds a plugin.
func (*ServerPluginContainer) DoPostConnAccept ¶
func (p *ServerPluginContainer) DoPostConnAccept(conn net.Conn) bool
DoPostConnAccept handle accepted conn
func (*ServerPluginContainer) DoPostReadRequestBody ¶
func (p *ServerPluginContainer) DoPostReadRequestBody(body interface{}) error
DoPostReadRequestBody invokes DoPostReadRequestBody plugin.
func (*ServerPluginContainer) DoPostReadRequestHeader ¶
func (p *ServerPluginContainer) DoPostReadRequestHeader(r *rpc.Request) error
DoPostReadRequestHeader invokes DoPostReadRequestHeader plugin.
func (*ServerPluginContainer) DoPostWriteResponse ¶
func (p *ServerPluginContainer) DoPostWriteResponse(resp *rpc.Response, body interface{}) error
DoPostWriteResponse invokes DoPostWriteResponse plugin.
func (*ServerPluginContainer) DoPreReadRequestBody ¶
func (p *ServerPluginContainer) DoPreReadRequestBody(body interface{}) error
DoPreReadRequestBody invokes DoPreReadRequestBody plugin.
func (*ServerPluginContainer) DoPreReadRequestHeader ¶
func (p *ServerPluginContainer) DoPreReadRequestHeader(r *rpc.Request) error
DoPreReadRequestHeader invokes DoPreReadRequestHeader plugin.
func (*ServerPluginContainer) DoPreWriteResponse ¶
func (p *ServerPluginContainer) DoPreWriteResponse(resp *rpc.Response, body interface{}) error
DoPreWriteResponse invokes DoPreWriteResponse plugin.
func (*ServerPluginContainer) DoRegister ¶
func (p *ServerPluginContainer) DoRegister(name string, rcvr interface{}, metadata ...string) error
DoRegister invokes DoRegister plugin.
func (*ServerPluginContainer) GetAll ¶
func (p *ServerPluginContainer) GetAll() []IPlugin
GetAll returns all activated plugins
func (*ServerPluginContainer) GetByName ¶
func (p *ServerPluginContainer) GetByName(pluginName string) IPlugin
GetByName returns a plugin instance by it's name
func (*ServerPluginContainer) GetDescription ¶
func (p *ServerPluginContainer) GetDescription(plugin IPlugin) string
GetDescription returns the name of a plugin, if no GetDescription() implemented it returns an empty string ""
func (*ServerPluginContainer) GetName ¶
func (p *ServerPluginContainer) GetName(plugin IPlugin) string
GetName returns the name of a plugin, if no GetName() implemented it returns an empty string ""
func (*ServerPluginContainer) Remove ¶
func (p *ServerPluginContainer) Remove(pluginName string) error
Remove removes a plugin by it's name.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package main is a generated protocol buffer package.
|
Package main is a generated protocol buffer package. |
_examples
|
|