文档

1、实现一个简易的服务端

package main

import (
    "fmt"
    "net/http"
)

// 请求处理函数
func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("hello world!"))
}

func main() {

    // 路由
    http.HandleFunc("/", helloHandler)

    // 启动服务
    fmt.Printf("http server starting at http://127.0.0.1:9090\n")

    err := http.ListenAndServe(":9090", nil)

    if err != nil {
        fmt.Printf("http server failed, err:%v\n", err)
        return
    }
}

请求示例

$ curl http://127.0.0.1:9090/
hello world!

示例

2、实现一个类似 https://httpbin.org/的服务,返回请求的信息

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "strings"
)

type Result struct {
    Args    map[string]string      `json:"args"`
    Headers map[string]string      `json:"headers"`
    Form    map[string]string      `json:"form"`
    Json    map[string]interface{} `json:"json"`
    Method  string                 `json:"method"`
    Data    string                 `json:"data"`
    Url     string                 `json:"url"`
    Origin  string                 `json:"origin"`
}

func echoHandler(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()

    ret := &Result{}
    ret.Method = r.Method
    ret.Origin = r.RemoteAddr

    // 完整url
    scheme := "http://"
    if r.TLS != nil {
        scheme = "https://"
    }

    ret.Url = strings.Join([]string{scheme, r.Host, r.RequestURI}, "")

    // raw data
    data, _ := io.ReadAll(r.Body)
    ret.Data = string(data)

    // form
    // r.ParseForm()
    // ret.Form = make(map[string]string)
    // for key, _ := range r.PostForm {
    //  ret.Form[key] = r.PostForm.Get(key)
    // }

    // 通过raw data解析
    ret.Form = make(map[string]string)
    form, err := url.ParseQuery(string(data))
    if err != nil {
        for key, _ := range form {
            ret.Form[key] = form.Get(key)
        }
    }

    // json
    ret.Json = make(map[string]interface{})
    json.Unmarshal(data, &ret.Json)

    // args
    ret.Args = make(map[string]string)
    for key, _ := range r.URL.Query() {
        ret.Args[key] = r.URL.Query().Get(key)
    }

    // header
    ret.Headers = make(map[string]string)

    for key, _ := range r.Header {
        ret.Headers[key] = r.Header.Get(key)
    }

    body, _ := json.Marshal(ret)
    w.Write(body)
}

func main() {

    // 路由
    http.HandleFunc("/", echoHandler)

    // 启动服务
    fmt.Printf("http server starting at http://127.0.0.1:9090\n")

    err := http.ListenAndServe(":9090", nil)

    if err != nil {
        fmt.Printf("http server failed, err:%v\n", err)
        return
    }
}

注意:由于请求体只能读取一次,所以form和rawData只能取到一个

通过客户端发起请求

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
)

func main() {
    targetUrl := "http://127.0.0.1:9090"

    // url args
    u, _ := url.ParseRequestURI(targetUrl)

    params := url.Values{}
    params.Set("name", "Tom")
    params.Set("age", "18")

    u.RawQuery = params.Encode() // URL encode

    // json
    data := make(map[string]interface{})
    data["name"] = "Tom"
    data["age"] = 12

    resqdata, _ := json.Marshal(data)

    client := &http.Client{}
    req, _ := http.NewRequest("POST", u.String(), bytes.NewReader(resqdata))

    // header
    req.Header.Add("X-Token", "token")
    req.Header.Add("Content-Type", "application/json")

    resp, _ := client.Do(req)
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))

}

返回结果

{
    "args": {
        "age": "18",
        "name": "Tom"
    },
    "headers": {
        "Accept-Encoding": "gzip",
        "Content-Length": "23",
        "Content-Type": "application/json",
        "User-Agent": "Go-http-client/1.1",
        "X-Token": "token"
    },
    "form": {},
    "json": {
        "age": 12,
        "name": "Tom"
    },
    "method": "POST",
    "data": "{\"age\":12,\"name\":\"Tom\"}",
    "url": "http://127.0.0.1:9090/?age=18&name=Tom",
    "origin": "127.0.0.1:62103"
}

可以看到,我们的服务端可以正确获取到请求的参数信息和json请求体,以及请求头部信息

【参考 】

  1. 深入探索Go语言net/http包:构建高性能的Web服务
  2. Golang:发起http请求-GET带参数、POST发送Form和JSON数据