go http内存泄漏问题分析。

1、https://segmentfault.com/a/1190000020086816

2、demo验证

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    _ "net/http/pprof"
    "net/url"
    "time"
)

type auth struct {
    Username string `json:"username"`
    Pwd      string `json:"password"`
}

func main() {

    //开启pprof协程来进行监控
    go func() {
        log.Println(http.ListenAndServe("0.0.0.0:6060", nil))
    }()

    for {
        time.Sleep(100 * time.Millisecond)
        //go postWithJson()
        go get()
    }

    time.Sleep(40 * time.Second)
    //get()
    //postWithJson()
    //postWithUrlencoded()
}

func get() {
    //get请求
    //http.Get的参数必须是带http://协议头的完整url,不然请求结果为空
    resp, _ := http.Get("http://localhost:8080/login2?username=admin&password=123456")
    //defer resp.Body.Close()
    //    body, _ := ioutil.ReadAll(resp.Body)
    //fmt.Println(string(body))
    fmt.Printf("Get request result: %s\n", resp)
}

func postWithJson() {
    //post请求提交json数据
    auths := auth{"admin", "123456"}
    ba, _ := json.Marshal(auths)
    resp, _ := http.Post("http://localhost:8080/login1", "application/json", bytes.NewBuffer([]byte(ba)))
    //defer resp.Body.Close()
    //body, _ := ioutil.ReadAll(resp.Body)
    fmt.Printf("Post request with json result: %s\n", resp)
}

func postWithUrlencoded() {
    //post请求提交application/x-www-form-urlencoded数据
    form := make(url.Values)
    form.Set("username", "admin")
    form.Add("password", "123456")
    resp, _ := http.PostForm("http://localhost:8080/login2", form)
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Printf("Post request with application/x-www-form-urlencoded result: %s\n", string(body))
}
http_client.go
package main

import (
    "encoding/json"
    "log"
    "net/http"
)

func main() {

    http.HandleFunc("/login1", login1)
    http.HandleFunc("/login2", login2)
    http.ListenAndServe("0.0.0.0:8080", nil)
}

type Resp struct {
    Code string `json:"code"`
    Msg  string `json:"msg"`
}

type Auth struct {
    Username string `json:"username"`
    Pwd      string `json:"password"`
}

//post接口接收json数据
func login1(writer http.ResponseWriter, request *http.Request) {
    var auth Auth
    if err := json.NewDecoder(request.Body).Decode(&auth); err != nil {
        request.Body.Close()
        log.Fatal(err)
    }
    var result Resp
    if auth.Username == "admin" && auth.Pwd == "123456" {
        result.Code = "200"
        result.Msg = "登录成功"
    } else {
        result.Code = "401"
        result.Msg = "账户名或密码错误"
    }
    if err := json.NewEncoder(writer).Encode(result); err != nil {
        log.Fatal(err)
    }
}

//接收x-www-form-urlencoded类型的post请求或者普通get请求
func login2(writer http.ResponseWriter, request *http.Request) {
    request.ParseForm()
    username, uError := request.Form["username"]
    pwd, pError := request.Form["password"]

    var result Resp
    if !uError || !pError {
        result.Code = "401"
        result.Msg = "登录失败"
    } else if username[0] == "admin" && pwd[0] == "123456" {
        result.Code = "200"
        result.Msg = "登录成功"
    } else {
        result.Code = "203"
        result.Msg = "账户名或密码错误"
    }
    if err := json.NewEncoder(writer).Encode(result); err != nil {
        log.Fatal(err)
    }
}
test_server.go

3、pprof分析下,get/post分别不同场景下的是否resp.Body.Close()的问题

 

 

ioutil.ReadAll注意事项:https://blog.csdn.net/xuefeng1207/article/details/87939737

在golang中,实现一个普通的http接口可以处理get请求和x-www-form-urlencoded类型的post请求,而如果想实现处理json数据的post请求,则需要用另外的方式实现,接收的参数要从request.Body中读取:

posted @ 2020-10-15 15:57  谁给起个名  阅读(686)  评论(0)    收藏  举报