go-micro server 服务器
go-micro 支持很多通信协议:http、tcp、grpc等,支持的编码方式也很多有json、protobuf、bytes、jsonrpc等。也可以根据自己的需要实现通信协议和编码方式。go-micro 默认的通信协议是http,默认的编码方式是protobuf。
主要代码定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | type Server interface { Options() Options Init(...Option) error Handle(Handler) error NewHandler( interface {}, ...HandlerOption) Handler NewSubscriber(string, interface {}, ...SubscriberOption) Subscriber Subscribe(Subscriber) error Register() error Deregister() error Start() error Stop() error String() string } type Message interface { Topic() string Payload() interface {} ContentType() string } type Request interface { Service() string Method() string ContentType() string Request() interface {} // indicates whether the request will be streamed Stream() bool } // Stream represents a stream established with a client. // A stream can be bidirectional which is indicated by the request. // The last error will be left in Error(). // EOF indicated end of the stream. type Stream interface { Context() context.Context Request() Request Send( interface {}) error Recv( interface {}) error Error() error Close() error } type Option func (*Options) type HandlerOption func (*HandlerOptions) type SubscriberOption func (*SubscriberOptions) |
server 启动时会注册 handler ,即方法路由。注册机制是利用反射,把对象的信息完全提取出来,解析出结构体内的方法及方法的参数,保存到一个map内: map[结构体名称][方法信息集合]
1 2 3 4 5 6 7 8 9 10 11 12 | func (s *rpcServer) Handle(h Handler) error { s.Lock() defer s.Unlock() if err := s.rpc.register(h.Handler()); err != nil { return err } s.handlers[h.Name()] = h return nil } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | func (server *server) register(rcvr interface {}) error { server.mu.Lock() defer server.mu.Unlock() if server.serviceMap == nil { server.serviceMap = make( map [string]*service) } s := new(service) s.typ = reflect.TypeOf(rcvr) s.rcvr = reflect.ValueOf(rcvr) sname := reflect.Indirect(s.rcvr).Type().Name() if sname == "" { log.Fatal( "rpc: no service name for type" , s.typ.String()) } if !isExported(sname) { s := "rpc Register: type " + sname + " is not exported" log.Log(s) return errors.New(s) } if _, present := server.serviceMap[sname]; present { return errors.New( "rpc: service already defined: " + sname) } s.name = sname s.method = make( map [string]*methodType) // Install the methods for m := 0; m < s.typ.NumMethod(); m++ { method := s.typ.Method(m) if mt := prepareMethod(method); mt != nil { s.method[method.Name] = mt } } if len(s.method) == 0 { s := "rpc Register: type " + sname + " has no exported methods of suitable type" log.Log(s) return errors.New(s) } server.serviceMap[s.name] = s return nil } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | type methodType struct { sync.Mutex // protects counters method reflect.Method ArgType reflect.Type ReplyType reflect.Type ContextType reflect.Type stream bool } type service struct { name string // name of service rcvr reflect.Value // receiver of methods for the service typ reflect.Type // type of the receiver method map [string]*methodType // registered methods } |
路由信息处理完后,主要的工作就已经完成了,然后注册服务并启动服务,启动的服务是一个http的服务。启动流程如下:
you are the best!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现