go net/http包服务器编程

1
回复
143
查看
[复制链接]

微信扫一扫 分享朋友圈

3

主题

9

帖子

15

积分

新手上路

Rank: 1

积分
15
发表于 2023-2-10 17:05:45 | 显示全部楼层 |阅读模式
Go语言标准库内建net/http包,不仅提供了Http 发送POST、GET等请求的客户端方法,还提供了编写服务器处理的一些方法。下面简单介绍如何启动一个服务器,并注册处理程序。最后介绍gin框架中启动服务的原理。

HTTP Server

net/http包提供http.ListenAndServe()可以直接创建一个监听服务器。用来侦听TCP网络地址addr,然后使用处理程序调用来处理传入的请求。如果handler为nil,则使用默认的http.DefaultServeMux进行处理。
当调用http.Handle()或http.HandleFunc()时,默认注入http.DefaultServeMux中。http.DefaultServeMux是ServeMux结构体的实例。ServeMux是一个HTTP请求多路复用器。它将每个传入请求的URL与已注册模式列表进行匹配,并调用匹配模式的处理程序。
//注册处理程序需要实现Handler接口
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}

//src/net/http/server.go
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
//在DefaultServeMux中注册处理程序
func Handle(pattern string, handler Handler) {
    DefaultServeMux.Handle(pattern, handler)
}
//在DefaultServeMux中注册处理程序函数
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
示例代码:
type HttpHandler struct {
}

func (*HttpHandler) ServeHTTP(writer http.ResponseWriter, http *http.Request) {
        fmt.Println(http.URL, http.Header)
        writer.Write([]byte("hello"))
}

func main() {
        log.Fatal(http.ListenAndServe(":8080", new(HttpHandler)))
}如果需要更多地控制服务端行为可以自定义http.Server。
server := http.Server{
        Addr:         "127.0.0.1:9001",
        Handler:      new(HttpHandler),
        ReadTimeout:  10 * time.Second,
        WriteTimeout: 10 * time.Second,
}
//http.Handle("/one", new(HttpHandler))
http.HandleFunc("/foo", func(writer http.ResponseWriter, request *http.Request) {
        writer.Write([]byte("hello,I'm foo!"))
})
log.Fatal(server.ListenAndServe())下面写法也是很常见的,先使用net.Listen创建一个listener,然后调用http.Serve启动监听程序
func main() {
        lis, err := net.Listen("TCP", "8080")
        if err != nil {
                fmt.Printf("listen addr fail,err:%v\n", err)
                return
        }
        http.HandleFunc("/foo", func(writer http.ResponseWriter, request *http.Request) {
                writer.Write([]byte("hello,I'm foo!"))
        })
        log.Fatal(http.Serve(lis, nil))
        //或者这样也可以
        //server := &http.Server{}
        //server.Serve(lis)
}Gin框架Web处理器原理

在我们使用gin启动一个web服务,下面几行代码就能完成,是不是很简单。
func main() {
        r := gin.Default()
        //router.InitRouter(r)
        err := r.Run(config.C.Server.Addr)
        if err != nil {
                log.Fatal(err)
        }
}那么它是如何处理的呢?关键时看Engine.Run方法怎么运行的。
// 此处Engine实现了http.Handler 接口
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c := engine.pool.Get().(*Context)
c.writermem.reset(w)
c.Request = req
c.reset()

engine.handleHTTPRequest(c)

engine.pool.Put(c)
}
//返回Engine指针对象
func (engine *Engine) Handler() http.Handler {
if !engine.UseH2C {
  return engine
}

h2s := &http2.Server{}
return h2c.NewHandler(engine, h2s)
}
//启动服务
func (engine *Engine) Run(addr ...string) (err error) {
defer func() { debugPrintError(err) }()

if engine.isUnsafeTrustedProxies() {
  debugPrint("[WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.\n" +
   "Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.")
}

address := resolveAddress(addr)
debugPrint("Listening and serving HTTP on %s\n", address)
//看这里是不是调用的标准库的方法
err = http.ListenAndServe(address, engine.Handler())
return
}
回复

使用道具 举报

1

主题

12

帖子

23

积分

新手上路

Rank: 1

积分
23
发表于 2025-6-18 21:36:32 | 显示全部楼层
嘘,低调。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表