美文网首页
Golang Web 的一个编程范例

Golang Web 的一个编程范例

作者: 斗為帝車 | 来源:发表于2018-03-06 14:52 被阅读0次

    Go语言编写HTTP Web网络服务有着各种各样的框架和模型,而阅读成熟的实现也是一个好的高效的学习应用途径。

    Docker(moby)中对服务的一个实现我认为是比较好的编程范例。

    1. 定义一个通用的Http接口。
    // https://github.com/moby/moby/blob/master/api/server/httputils/httputils.go
    
    type APIFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error
    
    1. 定义路由接口
    //  https://github.com/moby/moby/blob/master/api/server/router/router.go
    
    // Router defines an interface to specify a group of routes to add to the docker server.
    type Router interface {
        // Routes returns the list of routes to add to the docker server.
        Routes() []Route
    }
    
    // Route defines an individual API route in the docker server.
    type Route interface {
        // Handler returns the raw function to create the http handler.
        Handler() httputils.APIFunc
        // Method returns the http method that the route responds to.
        Method() string
        // Path returns the subpath where the route responds to.
        Path() string
    }
    

    当然也有一个本地的实现,参见同目录下的 local.go文件。

    1. 定义各种逻辑处理
    func  (h *xxhandler) handler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
     ......
    }
    

    这些逻辑实现在 github.com/docker/docker/api/server/router 目录下,每个子目录都是一组,而且每组都实现了Router接口。

    1. 装配

    首先需要一个转换函数:

    // https://github.com/moby/moby/blob/master/api/server/server.go
    
    func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
            // Define the context that we'll pass around to share info
            // like the docker-request-id.
            //
            // The 'context' will be used for global data that should
            // apply to all requests. Data that is specific to the
            // immediate function being called should still be passed
            // as 'args' on the function call.
            ctx := context.WithValue(context.Background(), dockerversion.UAStringKey, r.Header.Get("User-Agent"))
            handlerFunc := s.handlerWithGlobalMiddlewares(handler)
    
            vars := mux.Vars(r)
            if vars == nil {
                vars = make(map[string]string)
            }
    
            if err := handlerFunc(ctx, w, r, vars); err != nil {
                statusCode := httputils.GetHTTPErrorStatusCode(err)
                if statusCode >= 500 {
                    logrus.Errorf("Handler for %s %s returned error: %v", r.Method, r.URL.Path, err)
                }
                httputils.MakeErrorHandler(err)(w, r)
            }
        }
    }
    

    httputils.APIFunc转换为标准http.HandlerFunc,一个妙招。

    下来在createMux 这个函数对所有的Router进行遍历,组装为标准的mux.Router,搞定。

    点评

    这个实现具有一个很好的范例,尤其在httputils.APIFunc上做的非常棒,不仅兼顾了context,还有一个返回的error,可以在处理不同的逻辑时灵活运用。

    相关文章

      网友评论

          本文标题:Golang Web 的一个编程范例

          本文链接:https://www.haomeiwen.com/subject/xialfftx.html