Go语言搭建http服务 北京go周末班老男孩培训

    /    2019-06-26

更多内容请关注微信公众号:oldboygo


Go语言"net/http"包提供了HTTP客户端和服务端的实现。Get、Head、Post和PostForm函数发出HTTP/ HTTPS请求。

创建一个http服务,大致需要经历两个过程,首先需要注册路由,即提供url模式和handler函数的映射,其次就是实例化一个server对象,并开启对客户端的监听。

常用函数和方法:

func (srv *Server) ListenAndServe() error

ListenAndServe监听srv.Addr指定的TCP地址,并且会调用Serve方法接收到的连接。如果srv.Addr为空字符串,会使用":http"。

func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

HandleFunc注册一个处理器函数handler和对应的模式pattern(注册到DefaultServeMux)。ServeMux的文档解释了模式的匹配机制。

func Handle(pattern string, handler Handler)

Handle注册HTTP处理器handler和对应的模式pattern(注册到DefaultServeMux)。如果该模式已经注册有一个处理器,Handle会panic。ServeMux的文档解释了模式的匹配机制。

type Server struct {
    Addr           string        // 监听的TCP地址,如果为空字符串会使用":http"
    Handler        Handler       // 调用的处理器,如为nil会调用http.DefaultServeMux
    ReadTimeout    time.Duration // 请求的读取操作在超时前的最大持续时间
    WriteTimeout   time.Duration // 回复的写入操作在超时前的最大持续时间
    MaxHeaderBytes int           // 请求的头域最大长度,如为0则用DefaultMaxHeaderBytes
    TLSConfig      *tls.Config   // 可选的TLS配置,用于ListenAndServeTLS方法
    // TLSNextProto(可选地)指定一个函数来在一个NPN型协议升级出现时接管TLS连接的所有权。
    // 映射的键为商谈的协议名;映射的值为函数,该函数的Handler参数应处理HTTP请求,
    // 并且初始化Handler.ServeHTTP的*Request参数的TLS和RemoteAddr字段(如果未设置)。
    // 连接在函数返回时会自动关闭。
    TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
    // ConnState字段指定一个可选的回调函数,该函数会在一个与客户端的连接改变状态时被调用。
    // 参见ConnState类型和相关常数获取细节。
    ConnState func(net.Conn, ConnState)
    // ErrorLog指定一个可选的日志记录器,用于记录接收连接时的错误和处理器不正常的行为。
    // 如果本字段为nil,日志会通过log包的标准日志记录器写入os.Stderr。
    ErrorLog *log.Logger
    // 内含隐藏或非导出字段
}

Server类型定义了运行HTTP服务端的参数。Server的零值是合法的配置。

func (srv *Server) ListenAndServe() error

ListenAndServe监听srv.Addr指定的TCP地址,并且会调用Serve方法接收到的连接。如果srv.Addr为空字符串,会使用":http"。

Go语言创建http服务有如下三种实现方式:

方式一:

package main

import (
    "io"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/hello", hello)
    err := http.ListenAndServe(":8080"nil)
    if err != nil {
        log.Panic(err)
    }
}
func hello(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "hello")
}

上述代码解释:

首先注册一个hello函数给“/hello”,当浏览器浏览“/hello”的时候,会调用hello函数,其次开始监听和服务,“:8080”表示本机所有的ip地址的8080口。

方式二:

package main

import (
    "io"
    "log"
    "net/http"
)

func main() {
    http.Handle("/hello", &ServeMux{})
    err := http.ListenAndServe(":8080"nil)
    if err != nil {
        log.Panic(err)
    }
}

type ServeMux struct{}

func (p *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "hello world")
}

其实方式2就是方式1的一种包装形式,方式1只是将func hello(w http.ResponseWriter,r *http.Request)转化成type HandlerFunc func(ResponseWriter, *Request)类型,而HandlerFunc又实现了Handler接口,所以到这里情况就和方式2一致了。

方式三,(自定义路由,不使用DefaultServeMux)

package main

import (
    "io"
    "log"
    "net/http"
)

func main() {
    router := &http.Server{Addr: ":8080", Handler: &RouterMux{}}
    err := router.ListenAndServe()
    if err != nil {
        log.Panic(err)
    }
}

type RouterMux struct{}

func (p *RouterMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    switch r.URL.Path {
    case "/hello":
        io.WriteString(w, "hello router")
    case "/hello2":
        io.WriteString(w, "hello world !!!")
    default:
        io.WriteString(w, r.URL.Path)
    }
}

根据http.ListenAndServe(string,Handler)方法可以看出,方式1和方式2就是在方式3的基础上做了一些简单的封装。


(0)

分享至