最近在寫 go 時,碰到一個地雷,花了一整天,最終發現是很基本的問題,看來自己功力還是太淺,在這方面還需要多加強,在這裡紀錄一下歷程

首先我最近因為 Demo 需要,做了一個 guser proxy (gusher介紹),降低其他 application 存取複雜度。

func main() {
    u:="http://xxx.com/api"
    client := &http.Client{}
    i:=0
    for i<100 {
        v := url.Values{}
        v.Add("content", "test")
        req, err := http.NewRequest("POST", u, bytes.NewBufferString(v.Encode()))
        _,err:=client.Do(req)
        i++
    }

}

這是一個簡單的 simple code,基本上就是重複的對一個 url 發出 request,我踩到的地雷就是因為個人偷懶,把 client 回傳的 response,直接忽略掉,導致資源一直咬著,最後會觸發 Socket:too many open files

後來利用 lsof 指令去觀看開啟資源,才發現這個疏忽,解法如下

func main() {
    u:="http://xxx.com/api"
    client := &http.Client{}
    i:=0
    for i<100 {
        v := url.Values{}
        v.Add("content", "test")
        req, err := http.NewRequest("POST", u, bytes.NewBufferString(v.Encode()))
        resp,err:=client.Do(req)
        resp.Body.Close()
        i++
    }

}

經過這次教訓,其實又認識了很多 linux 底層的東西,跟一些指令除錯,之前從同事那邊學到一句蠻受用的名言

每個 error 都乖乖處理,不要忽略,就不會發生不預期的錯誤

這次我給自己的一句話就是

每個 return 都要乖乖處理,不要偷懶,才不會忘記要做資源釋放