标准库 http 包的简单实用 
                                                    
                        
                    
                    
  
                    
                    通过几个例子来学习http包的简单实用
构建一个静态的文件服务器
func FileServer(root FileSystem) Handler
如果需要使用操作系统的文件系统,可以使用http.Dir
http.Handler(http.FileServer(http.Dir("/tmp")))
Example
package main
import (
    "log"
    "net/http"
)
func main() {
    log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("/Users/iamcyan/go_project/demo"))))
}
本地请求结果:
➜  demo pwd
/Users/iamcyan/go_project/demo
➜  demo tree
.
├── fmt.go
├── http.go
└── test
    └── a.txt
1 directory, 3 files
➜  demo curl http://localhost:8080/
<pre>
<a href=".idea/">.idea/</a>
<a href="fmt.go">fmt.go</a>
<a href="http.go">http.go</a>
<a href="test/">test/</a>
</pre>
➜  demo curl http://localhost:8080/test/
<pre>
<a href="a.txt">a.txt</a>
</pre>
➜  demo curl http://localhost:8080/test/a.txt
111
可以静态文件的访问设置路由前缀,比如我们给前面的路由加上前缀、doc/,能够返回同样的结果,代码如下:
package main
import (
    "log"
    "net/http"
)
func main() {
    http.Handle("/doc/", http.StripPrefix("/doc/", http.FileServer(http.Dir("/Users/iamcyan/go_project/demo"))))
    log.Fatal(http.ListenAndServe(":8080", nil))
}
返回示例:
➜  demo pwd
/Users/iamcyan/go_project/demo
➜  demo tree
.
├── fmt.go
├── http.go
└── test
    └── a.txt
1 directory, 3 files
➜  demo curl http://localhost:8080/doc/
<pre>
<a href=".idea/">.idea/</a>
<a href="fmt.go">fmt.go</a>
<a href="http.go">http.go</a>
<a href="test/">test/</a>
</pre>
➜  demo curl http://localhost:8080/doc/test/
<pre>
<a href="a.txt">a.txt</a>
</pre>
➜  demo
发送GET请求
func Get(url string) (resp *Response, err error)
返回下列code时,进行重定向,最大的重定向次数为10次。
301 (Moved Permanently)
302 (Found)
303 (See Other)
307 (Temporary Redirect)
308 (Permanent Redirect)
Example
func main() {
   resp, err := http.Get("http://www.google.com/robots.txt")
   if err != nil {
      log.Fatal(err)
   }
   robots, err := ioutil.ReadAll(resp.Body)
   resp.Body.Close()
   if err != nil {
      log.Fatal(err)
   }
   fmt.Printf("%s", robots)
}
注意:body 如何读取、body 读取完成之后必须关闭
Handle
handle方法可以将路由处理handler注册进DefaultServeMux
type countHandler struct {
    mu sync.Mutex
    c int
}
func (h *countHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)  {
    h.mu.Lock()
    defer h.mu.Unlock()
    h.c++
    fmt.Fprintf(w, "count is %d\n", h.c)
}
func main() {
    http.Handle("/count", new(countHandler))
    log.Fatal(http.ListenAndServe(":8080", nil))
}
HandleFunc
handle方法可以将路由处理handler function注册进DefaultServeMux
package main
import (
    "io"
    "log"
    "net/http"
)
func main() {
    h1 := func(w http.ResponseWriter, _ *http.Request) {
        io.WriteString(w, "Hello from a HandleFunc #1!\n")
    }
    h2 := func(w http.ResponseWriter, _ *http.Request) {
        io.WriteString(w, "Hello from a HandleFunc #2!\n")
    }
    http.HandleFunc("/", h1)
    http.HandleFunc("/endpoint", h2)
    log.Fatal(http.ListenAndServe(":8080", nil))
}
ListenAndServe
func ListenAndServe(addr string, handler Handler) error
监听网络端口,当连接到达时会调用handler处理程序。会开启TCP keep-alive。
默认的handler是nil,在这种情况下DefaultServeMux会被调用。
NotFoundHandler
func NotFoundHandler() Handler
Example
func main() {
    log.Fatal(http.ListenAndServe(":8080", http.NotFoundHandler()))
}
type ResponseWriter
ResponseWriter 接口用于 http 处理器生成HTTP 返回
在 Handler.ServerHTTP 返回后,ResponseWriter 不在被使用
实现改接口,需要实现3个方法
type ResponseWriter interfack {
    //设置http返回头,如 Header().Set()
    Header() Header
    Write([]byte) (int, err)
    //发送http状态码
    WriteHeader(statusCode int)
}
Example
func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/test", func(w http.ResponseWriter, req *http.Request) {
        // Before any call to WriteHeader or Write, declare
        // the trailers you will set during the HTTP
        // response. These three headers are actually sent in
        // the trailer.
        w.Header().Set("Trailer", "AtEnd1, AtEnd2")
        w.Header().Add("Trailer", "AtEnd3")
        w.Header().Set("Content-Type", "text/plain; charset=utf-8") // normal header
        w.WriteHeader(http.StatusOK)
        w.Header().Set("AtEnd1", "value 1")
        io.WriteString(w, "This HTTP response has both headers before this text and trailers at the end.\n")
        w.Header().Set("AtEnd2", "value 2")
        w.Header().Set("AtEnd3", "value 3") // These will appear as trailers.
    })
}
请求返回:
➜  demo curl -v http://localhost:8080/test
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /test HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Trailer: AtEnd1, AtEnd2
< Trailer: AtEnd3
< Date: Sun, 27 Dec 2020 05:36:51 GMT
< Transfer-Encoding: chunked
<
This HTTP response has both headers before this text and trailers at the end.
* Connection #0 to host localhost left intact
* Closing connection 0
func(*ServeMux) Handle
func (mux *ServeMux) Handle(pattern string, handler Handler)
type apiHandler struct{}
func (apiHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}
func main() {
    mux := http.NewServeMux()
    mux.Handle("/api/", apiHandler{})
    mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        // The "/" pattern matches everything, so we need to check
        // that we're at the root here.
        if req.URL.Path != "/" {
            http.NotFound(w, req)
            return
        }
        fmt.Fprintf(w, "Welcome to the home page!")
    })
}
                        
                        本作品采用《CC 协议》,转载必须注明作者和本文链接
          
          
          
                关于 LearnKu
              
                    
                    
                    
 
推荐文章: