Go Web服务器代码流

Go Web服务器代码流,go,Go,我正在使用Go using net/HTTP包创建一个简单的web服务器。 简单的代码如下所示: package main import ( "fmt" "net/http" ) type hotdog int func (m hotdog) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Any code you want in this func") } func main()

我正在使用Go using net/HTTP包创建一个简单的web服务器。 简单的代码如下所示:

package main
import (
    "fmt"
    "net/http"
)
type hotdog int
func (m hotdog) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Any code you want in this func")
}
func main() {
    var d hotdog
    http.ListenAndServe(":8080", d)
}
我想知道引擎盖下发生了什么? 如果我没有错的话

ListenAndServe()接受地址和处理程序,此函数在库中运行

func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler}
    return server.ListenAndServe()
  } 
在这个函数调用ListendServe之后

func (srv *Server) ListenAndServe() error {
    addr := srv.Addr
    if addr == "" {
        addr = ":http"
    }
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        return err
    }
    return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
  }
现在调用Serve函数。但是我无法理解这个参数(
tcpKeepAliveListener{ln(*net.TCPListener)}
)是如何转换为 服务函数中的(
l net.Listener

func (srv *Server) Serve(l net.Listener) error {
    defer l.Close()
    if fn := testHookServerServe; fn != nil {
        fn(srv, l)
    }
    var tempDelay time.Duration // how long to sleep on accept failure

    if err := srv.setupHTTP2_Serve(); err != nil {
        return err
    }

    srv.trackListener(l, true)
    defer srv.trackListener(l, false)

    baseCtx := context.Background() // base is always background, per Issue 16220
    ctx := context.WithValue(baseCtx, ServerContextKey, srv)
    for {
        rw, e := l.Accept()
        if e != nil {
            select {
            case <-srv.getDoneChan():
                return ErrServerClosed
            default:
            }
            if ne, ok := e.(net.Error); ok && ne.Temporary() {
                if tempDelay == 0 {
                    tempDelay = 5 * time.Millisecond
                } else {
                    tempDelay *= 2
                }
                if max := 1 * time.Second; tempDelay > max {
                    tempDelay = max
                }
                srv.logf("http: Accept error: %v; retrying in %v", e, tempDelay)
                time.Sleep(tempDelay)
                continue
            }
            return e
        }
        tempDelay = 0
        c := srv.newConn(rw)
        c.setState(c.rwc, StateNew) // before Serve can return
        go c.serve(ctx)
    }
  }
func(srv*Server)服务(l net.Listener)错误{
延迟l.关闭()
如果fn:=testHookServerServe;fn!=nil{
fn(srv,l)
}
var tempDelay time.Duration//接受失败时的睡眠时间
如果错误:=srv.setupHTTP2_Serve();错误!=nil{
返回错误
}
srv.trackListener(l,true)
延迟srv.trackListener(l,false)
baseCtx:=context.Background()//根据16220期,base始终是Background
ctx:=上下文.WithValue(baseCtx、ServerContextKey、srv)
为了{
rw,e:=l.Accept()
如果e!=nil{
挑选{
case max{
tempDelay=max
}
logf(“http:Accept错误:%v;在%v中重试”,e,tempDelay)
时间。睡眠(临时延迟)
持续
}
返回e
}
tempDelay=0
c:=srv.newConn(rw)
c、 setState(c.rwc,StateNew)//在服务返回之前
去发球(ctx)
}
}

调用的处理程序在哪里?

正如他们已经评论的那样,
net.Listener
类型是一个接口,
tcpkeepalivellistener
满足该接口,因此该类型是正确的

然后,要回答有关处理程序调用位置的问题,您需要深入了解代码流:

您发布的最后一段代码中的行
go c.serve(ctx)
正在调用
conn.serve()

这是一个函数包装器,然后为之前的相应处理程序集调用
ServeHTTP

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler
    if handler == nil {
        handler = DefaultServeMux
    }
    if req.RequestURI == "*" && req.Method == "OPTIONS" {
        handler = globalOptionsHandler{}
    }
    handler.ServeHTTP(rw, req)
}

tcpKeepAliveListener
是一个
net.Listener
。您必须进一步遵循代码才能找到调用处理程序的位置。事实上,更具体地说,
net.Listener
是一个接口,
tcpKeepAliveListener
实现了该接口。您能更详细地说明这一行tcpKeepAliveListener{ln(*net.TCPListener)}tcsKeepAlive是struct类型的,所以我们在这里初始化它,但是它是如何工作的{ln(*net.TCPListener)}@kartik:你能比“它是如何工作的”更具体一点吗?由
net.Listen
返回的
ln
是一个
*net.TCPListener
,它被断言为在
tcpKeepAliveListener
@kartik中使用,也许这可以澄清一点:谢谢我了解了Handler
// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
    srv *Server
}

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler
    if handler == nil {
        handler = DefaultServeMux
    }
    if req.RequestURI == "*" && req.Method == "OPTIONS" {
        handler = globalOptionsHandler{}
    }
    handler.ServeHTTP(rw, req)
}
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler
    if handler == nil {
        handler = DefaultServeMux
    }
    if req.RequestURI == "*" && req.Method == "OPTIONS" {
        handler = globalOptionsHandler{}
    }
    handler.ServeHTTP(rw, req)
}