1. Http

    Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现。

    Go语言内置的net/http包提供了HTTP客户端和服务端的实现。

    1.1.2. HTTP协议

    超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。

    1.1.3. HTTP客户端

    基本的HTTP/HTTPS请求 Get、Head、Post和PostForm函数发出HTTP/HTTPS请求。

    程序在使用完response后必须关闭回复的主体。

    1. if err != nil {
    2. // handle error
    3. }
    4. defer resp.Body.Close()
    5. body, err := ioutil.ReadAll(resp.Body)
    6. // ...
    1. package main
    2. import (
    3. "fmt"
    4. "io/ioutil"
    5. "net/http"
    6. )
    7. func main() {
    8. resp, err := http.Get("https://www.5lmh.com/")
    9. if err != nil {
    10. fmt.Println("get failed, err:", err)
    11. return
    12. }
    13. defer resp.Body.Close()
    14. body, err := ioutil.ReadAll(resp.Body)
    15. if err != nil {
    16. fmt.Println("read from resp.Body failed,err:", err)
    17. return
    18. }
    19. fmt.Print(string(body))
    20. }

    将上面的代码保存之后编译成可执行文件,执行之后就能在终端打印liwenzhou.com网站首页的内容了,我们的浏览器其实就是一个发送和接收HTTP协议数据的客户端,我们平时通过浏览器访问网页其实就是从网站的服务器接收HTTP数据,然后浏览器会按照HTML、CSS等规则将网页渲染展示出来。

    1.1.5. 带参数的GET请求示例

    关于GET请求的参数需要使用Go语言内置的net/url这个标准库来处理。

    1. func main() {
    2. apiUrl := "http://127.0.0.1:9090/get"
    3. // URL param
    4. data := url.Values{}
    5. data.Set("name", "枯藤")
    6. data.Set("age", "18")
    7. u, err := url.ParseRequestURI(apiUrl)
    8. if err != nil {
    9. }
    10. u.RawQuery = data.Encode() // URL encode
    11. fmt.Println(u.String())
    12. resp, err := http.Get(u.String())
    13. if err != nil {
    14. fmt.Println("post failed, err:%v\n", err)
    15. return
    16. }
    17. b, err := ioutil.ReadAll(resp.Body)
    18. if err != nil {
    19. fmt.Println("get resp failed,err:%v\n", err)
    20. return
    21. }
    22. fmt.Println(string(b))
    23. }

    对应的Server端HandlerFunc如下:

    1.1.6. Post请求示例

    上面演示了使用net/http包发送GET请求的示例,发送POST请求的示例代码如下:

    1. package main
    2. import (
    3. "fmt"
    4. "io/ioutil"
    5. "net/http"
    6. "strings"
    7. )
    8. // net/http post demo
    9. func main() {
    10. url := "http://127.0.0.1:9090/post"
    11. // 表单数据
    12. //contentType := "application/x-www-form-urlencoded"
    13. //data := "name=枯藤&age=18"
    14. // json
    15. contentType := "application/json"
    16. data := `{"name":"枯藤","age":18}`
    17. resp, err := http.Post(url, contentType, strings.NewReader(data))
    18. if err != nil {
    19. fmt.Println("post failed, err:%v\n", err)
    20. return
    21. }
    22. defer resp.Body.Close()
    23. b, err := ioutil.ReadAll(resp.Body)
    24. if err != nil {
    25. fmt.Println("get resp failed,err:%v\n", err)
    26. return
    27. }
    28. fmt.Println(string(b))
    29. }

    对应的Server端HandlerFunc如下:

    1. func postHandler(w http.ResponseWriter, r *http.Request) {
    2. // 1. 请求类型是application/x-www-form-urlencoded时解析form数据
    3. r.ParseForm()
    4. fmt.Println(r.PostForm) // 打印form数据
    5. fmt.Println(r.PostForm.Get("name"), r.PostForm.Get("age"))
    6. b, err := ioutil.ReadAll(r.Body)
    7. if err != nil {
    8. fmt.Println("read request.Body failed, err:%v\n", err)
    9. return
    10. }
    11. fmt.Println(string(b))
    12. answer := `{"status": "ok"}`
    13. w.Write([]byte(answer))
    14. }
    1. client := &http.Client{
    2. CheckRedirect: redirectPolicyFunc,
    3. }
    4. resp, err := client.Get("http://5lmh.com")
    5. // ...
    6. req, err := http.NewRequest("GET", "http://5lmh.com", nil)
    7. // ...
    8. req.Header.Add("If-None-Match", `W/"wyzzy"`)
    9. resp, err := client.Do(req)
    10. // ...

    1.1.8. 自定义Transport

    要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport:

    Client和Transport类型都可以安全的被多个go程同时使用。出于效率考虑,应该一次建立、尽量重用。

    1.1.9. 服务端

    默认的Server

    ListenAndServe使用指定的监听地址和处理器启动一个HTTP服务端。处理器参数通常是nil,这表示采用包变量DefaultServeMux作为处理器。

    Handle和HandleFunc函数可以向DefaultServeMux添加处理器。

    1. http.Handle("/foo", fooHandler)
    2. http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
    3. fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
    4. })
    5. log.Fatal(http.ListenAndServe(":8080", nil))

    默认的Server示例

    使用Go语言中的net/http包来编写一个简单的接收HTTP请求的Server端示例,net/http包是对net包的进一步封装,专门用来处理HTTP协议的数据。具体的代码如下:

    1. // http server
    2. func sayHello(w http.ResponseWriter, r *http.Request) {
    3. fmt.Fprintln(w, "Hello 枯藤!")
    4. }
    5. func main() {
    6. http.HandleFunc("/", sayHello)
    7. err := http.ListenAndServe(":9090", nil)
    8. if err != nil {
    9. fmt.Printf("http server failed, err:%v\n", err)
    10. return
    11. }
    12. }

    自定义Server

    要管理服务端的行为,可以创建一个自定义的Server:

    1. s := &http.Server{
    2. Addr: ":8080",
    3. Handler: myHandler,
    4. ReadTimeout: 10 * time.Second,
    5. WriteTimeout: 10 * time.Second,
    6. MaxHeaderBytes: 1 << 20,
    7. log.Fatal(s.ListenAndServe())