Golang 學習筆記(一) - HTTP 客戶端 - 基礎

broqiang發表於2018-06-16

Go 封裝了非常方便的客戶端方法,不再需要藉助第三方包,就可以實現客戶端的請求。本篇文章主要將的是 Get 、 Post 、PostForm 三個基礎的方法。

這個方法非常的簡單,就是從指定的地址獲取到內容,可以簡單的理解成我們用瀏覽器開啟一個頁面。

Get 函式

語法:

Get(url string) (resp *Response, err error)

引數:

  • 字串型別的 url 地址,需要注意的是這裡要是完整地址,要加上 http://https:// 的地址

返回值:

  • *Response 如果獲取到了資料,會將資料儲存在 Response 中

  • error 如果請求資料的時候出現錯誤,會返回一個 error ,並將具體的錯誤記錄到 error 中

另外一種方式 Get 方法

可以通過 client 結構體的 Get() 方法獲取資料,其實兩種方式是一樣的,Get() 函式也是呼叫的結構體中的 Get() 方法。詳細的使用可以見示例中的用法

示例:

client.go

package main

import (
    "net/http"
    "log"
    "io/ioutil"
    "os"
    "fmt"
)

const url  = "https://broqiang.com"

func main() {
    // 方式一,直接通過 Get 函式
    resp, err := http.Get(url)
    ErrPrint(err)
    defer resp.Body.Close()

    // 拿到資料
    bytes, err := ioutil.ReadAll(resp.Body)
    ErrPrint(err)

    // 這裡要格式化再輸出,因為 ReadAll 返回的是位元組切片
    fmt.Println("------------- 方法一 ---------------")
    fmt.Printf("%s",bytes)

    // 方式二,通過 client 結構體的 Get 方法
    client := new(http.Client)
    // 或
    client = &http.Client{}

    resp, err = client.Get(url)
    ErrPrint(err)
    defer resp.Body.Close()

    res, err := ioutil.ReadAll(resp.Body)
    ErrPrint(err)
    fmt.Println("\n\n\n------------- 方法二 ---------------")
    fmt.Printf("%s",res)
}

func ErrPrint(err error)  {
    if err != nil {
        log.Fatalln(err)
        os.Exit(1)
    }
}

這個方法也比較簡單,就是通過 Post 方式和伺服器端互動。

POST 函式

語法:

(url string, contentType string, body io.Reader) (resp *Response, err error)

引數:

  • 字串型別的 url 地址,需要注意的是這裡要是完整地址,要加上 http://https:// 的地址

  • 字串型別的 contentType ,Post 提交資料的型別,常見的有下面 4 種:

    • application/x-www-form-urlencoded 不設定 enctype 屬性的原生 form 表單提交方式。

    • multipart/form-data 上傳檔案時的資料提交方式,相當於 form 表單的 enctype 等於 multipart/form-data 。

    • application/json 用來告訴服務端訊息主體是序列化後的 JSON 字串。

    • text/xml 它是一種使用 HTTP 作為傳輸協議,XML 作為編碼方式的遠端呼叫規範,和 json 作用型別。
  • 實現了 io.Reader 介面的資料。 如: 可以通過 strings.NewReader() 方法將普通字串實現 io.Reader 介面。

返回值:

  • *Response 如果獲取到了資料,會將資料儲存在 Response 中

  • error 如果請求資料的時候出現錯誤,會返回一個 error ,並將具體的錯誤記錄到 error 中

另外一種方式 Post 方法

可以通過 client 結構體的 Post() 方法獲取資料,其實兩種方式是一樣的,Post() 函式也是呼叫的結構體中的 Post() 方法。詳細的使用可以見示例中的用法

示例:

這個示例要和伺服器端互動資料,所以要有一個伺服器端和一個客戶端,伺服器端見目錄中的伺服器端內容(如果你很快就發現了這個文件,可能還沒來得及寫伺服器端)。

伺服器端程式碼

server.go

可以通過 http://localhost:8080/hello 來訪問伺服器端,但是要是 Post 方式才可以。測試的時候注意要先啟動伺服器端,再啟動客戶端。

package main

import (
    "net/http"
    "fmt"
    "log"
)

func main() {
    http.HandleFunc("/hello", func(w http.ResponseWriter, req *http.Request) {
        if req.Method == "POST" {
            fmt.Fprintf(w,"Hello %s\n",req.FormValue("name"))
            return
        }

        http.NotFound(w,req)
    })

    log.Fatalf("%v",http.ListenAndServe("localhost:8080",nil))
}

客戶端程式碼

client.go

package main

import (
    "log"
    "os"
    "net/http"
    "strings"
    "fmt"
    "io/ioutil"
    "io"
)

const url  = "http://localhost:8080/hello"

func main() {
    // 方式一,直接通過 Post 函式
    fmt.Println("------------- 方法一 ---------------")
    resp, err := http.Post(url,"application/x-www-form-urlencoded",
        strings.NewReader("name=Bro Qiang"))
    ErrPrint(err)
    defer resp.Body.Close()

    DataPrint(resp.Body)

    // 方式二,通過 client 結構體中的 Post 方法
    fmt.Println("------------- 方法二 ---------------")
    client := &http.Client{}
    resp, err = client.Post(url,"application/x-www-form-urlencoded",
        strings.NewReader("name=New Bro Qiang"))
    ErrPrint(err)
    defer resp.Body.Close()

    DataPrint(resp.Body)
}

func DataPrint(body io.ReadCloser) {
    // 拿到資料
    bytes, err := ioutil.ReadAll(body)
    ErrPrint(err)

    // 這裡要格式化再輸出,因為 ReadAll 返回的是位元組切片
    fmt.Printf("%s",bytes)
}

func ErrPrint(err error)  {
    if err != nil {
        log.Fatalln(err)
        os.Exit(1)
    }
}

這個方法是通過 Post 方式向伺服器端提交一個 form 表單,和 html 中的 form 表單提交型別。

PostForm 函式

語法:

PostForm(url string, data url.Values) (resp *Response, err error)

引數:

  • 字串型別的 url 地址,需要注意的是這裡要是完整地址,要加上 http://https:// 的地址

  • url.Values 型別的資料, 它的型別實際是一個 map[string][]string

返回值:

  • *Response 如果獲取到了資料,會將資料儲存在 Response 中

  • error 如果請求資料的時候出現錯誤,會返回一個 error ,並將具體的錯誤記錄到 error 中

另外一種方式 PostForm 方法

可以通過 client 結構體的 PostForm() 方法獲取資料,其實兩種方式是一樣的,PostForm() 函式也是呼叫的結構體中的 PostForm() 方法。詳細的使用可以見示例中的用法

示例:

建立一個伺服器端,用來接收 from 表單,並將資料在控制檯列印,並給客戶端返回是否成功。

建立一個客戶端,用來向伺服器端傳送 form 表單。

注意: 客戶端的 resp.Body 不要忘記關閉。

伺服器端

server.go

package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/form", MyForm)

    log.Fatalf("%v",
        http.ListenAndServe("localhost:8080", nil))
}

func MyForm(w http.ResponseWriter, r *http.Request) {
    err := r.ParseForm()
    if err != nil {
        http.Error(w, http.StatusText(http.StatusInternalServerError),
            http.StatusInternalServerError)
        return
    }

    formData := r.Form
    log.Printf("收到的資料: %v", formData)

    fmt.Fprintf(w, "提交成功")
}

客戶端程式碼

client.go

package main

import (
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "net/http"
    "os"
)

const url = "http://localhost:8080/form"

func main() {
    data := map[string][]string{"name": {"Bro Qiang"}, "gender": {"male"}}

    // 方法一:PostForm 函式
    resp, err := http.PostForm(url, data)
    ErrPrint(err)
    defer resp.Body.Close()

    DataPrint(resp.Body)

    // 方法二:client 結構體的 PostForm 方法
    client := &http.Client{}
    resp, err = client.PostForm(url, data)
    ErrPrint(err)
    defer resp.Body.Close()

    DataPrint(resp.Body)
}

func DataPrint(body io.ReadCloser) {
    // 拿到資料
    bytes, err := ioutil.ReadAll(body)
    ErrPrint(err)

    // 這裡要格式化再輸出,因為 ReadAll 返回的是位元組切片
    fmt.Printf("%s\n", bytes)
}

func ErrPrint(err error) {
    if err != nil {
        log.Fatalln(err)
        os.Exit(1)
    }
}

相關文章