GO CURL

Golang内置net/http包中http.Client结构用于实现HTTP客户端,因此无需借助第三方网络通信库(如libcurl)就可以直接使用GET或POST方式发起HTTP请求,实现远程请求页面。

type Client struct {
    Transport RoundTripper//HTTP请求创建机制,如果为空将会使用DefaultTransport。
    CheckRedirect func(req *Request, via []*Request) error//重定向策略
    Jar CookieJar //如果Jar为空,Cookie将不会在请求中发送,并会在响应中被忽略。
    Timeout time.Duration
}
属性描述
TransportHTTP事务用于处理客户端的请求并等待服务端的响应
CheckRedirect指定处理重定向的策略
Jar指定COOKIE的Jar
Timeout指定客户端请求的最大超时时间

http.Client被设计成上下两层结构

  • 上层:业务层

上层封装的基础方法可称之为业务层,因为调用方通常只需要关心请求的业务逻辑本身,而无需关心非业务相关的技术细节。

  • 下层:传输层

由于http.Client在底层抽象了http.RoundTripper接口,而http.Transport实现了该接口,从而能够处理更多细节,可将其视为下层的“传输层”。

Transport 指定执行HTTP请求的运行机制,可用于设置HTTP底层传输细节、HTTP代理、GZIP压缩、连接池及其管理、SSL认证等。

http.Client

发送JSON数据

func HTTPJson(method string, url string, params []byte) ([]byte, error) {
    body := bytes.NewBuffer(params)
    req, err := http.NewRequest(method, url, body)
    if err != nil {
        return nil, err
    }

    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    if resp != nil {
        defer resp.Body.Close()
    }
    if resp.StatusCode == http.StatusOK {
        msg := fmt.Sprintf("response status code %v", resp.StatusCode)
        return nil, errors.New(msg)
    }

    bs, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    return bs, nil
}

client.Do

func (c *Client) Do(req *Request) (*Response, error) {
    return c.do(req)
}
func HTTPDo(method string, url string, values url.Values) ([]byte, error) {
    body := strings.NewReader(values.Encode())

    req, err := http.NewRequest(method, url, body)
    if err != nil {
        return nil, err
    }

    //req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    //req.Header.Set("Cookie", cookie)
    //req.Header.Set("Connection", "keep-alive")
    //req.Header.Add("x-requested-with", "XMLHttpRequest") //AJAX

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    if resp != nil {
        defer resp.Body.Close()
    }
    if resp.StatusCode == http.StatusOK {
        msg := fmt.Sprintf("response status code %v", resp.StatusCode)
        return nil, errors.New(msg)
    }

    bs, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    return bs, nil
}

http.NewRequest

func NewRequest(method, url string, body io.Reader) (*Request, error) {
    return NewRequestWithContext(context.Background(), method, url, body)
}

http.Get

func Get(url string) (resp *Response, err error) {
    return DefaultClient.Get(url)
}
func (c *Client) Get(url string) (resp *Response, err error) {
    req, err := NewRequest("GET", url, nil)
    if err != nil {
        return nil, err
    }
    return c.Do(req)
}
func HTTPGet(url string) ([]byte, error) {
    //发送请求获取响应
    resp, err := http.Get(url)
    if err != nil {
        return nil, err
    }
    //结束网络释放资源
    if resp != nil {
        defer resp.Body.Close()
    }
    //判断响应状态码
    if resp.StatusCode != http.StatusOK {
        return nil, errors.New(fmt.Sprintf("response status code %v", resp.StatusCode))
    }

    //读取响应实体
    bs, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    return bs, nil
}

通过http.Get发起请求时,默认调用的是http.Client默认对象上的Get方法。

func Get(url string) (resp *Response, err error) {
    return DefaultClient.Get(url)
}

DefaultClient默认指向的正是http.Client的实例对象。

var DefaultClient = &Client{}

http.Get()方法返回值

func (c *Client) Get(url string) (resp *Response, err error) {
    req, err := NewRequest("GET", url, nil)
    if err != nil {
        return nil, err
    }
    return c.Do(req)
}
返回值类型描述
resp*http.Response响应对象
errerror错误对象

若请求过程中出现错误则error对象不为空,否则可通过resp响应对象获取响应码、响应头、响应实体等信息。

响应描述
resp.StatusCode获取响应状态码
resp.Header获取响应头
resp.Body获取响应实体

http.Post

func Post(url, contentType string, body io.Reader) (resp *Response, err error) {
    return DefaultClient.Post(url, contentType, body)
}
  • HTTP POST请求的参数需要通过url.Values进行编码和封装
func HTTPPost(url string, params url.Values, contentType string) ([]byte, error) {

    body := strings.NewReader(params.Encode())

    if contentType == "" {
        contentType = "application/x-www-form-urlencoded"
    }

    resp, err := http.Post(url, contentType, body)
    if err != nil {
        return nil, err
    }
    if resp != nil {
        defer resp.Body.Close()
    }
    if resp.StatusCode != http.StatusOK {
        return nil, errors.New(fmt.Sprintf("response status code %v", resp.StatusCode))
    }

    bs, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    return bs, nil
}

http.PostForm

func PostForm(url string, data url.Values) (resp *Response, err error) {
    return DefaultClient.PostForm(url, data)
}
func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
    return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}
func HTTPPostForm(url string, values url.Values) ([]byte, error) {
    resp, err := http.PostForm(url, values)
    if err != nil {
        return nil, err
    }
    if resp != nil {
        defer resp.Body.Close()
    }
    if resp.StatusCode != http.StatusOK {
        return nil, errors.New(fmt.Sprintf("response status code %v", resp.StatusCode))
    }

    bs, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    return bs, nil
}

url.Values

转化参数为 id=1&name=admin&pid=0 格式

func MakeParams(params url.Values) string {
    var keys []string
    for k := range params {
        keys = append(keys, k)
    }
    sort.Strings(keys)

    bb := bytes.Buffer{}
    for _, key := range keys {
        val := params.Get(key)
        bb.WriteString(key)
        bb.WriteString("=")
        bb.WriteString(val)
        bb.WriteString("&")
    }

    return strings.TrimRight(bb.String(), "&")
}
$ vim ./test/ins_test.go
package test

import (
    "gfw/web"
    "net/url"
    "testing"
)

func TestCurl(t *testing.T) {
    params := url.Values{}
    params.Add("id", "1")
    params.Add("name", "admin")
    params.Add("pid", "0")

    body := web.MakeParams(params)
    t.Log(body)
}
$ go test -v -run TestCurl ins_test.go
=== RUN   TestCurl
    ins_test.go:16: id=1&name=admin&pid=0
--- PASS: TestCurl (0.00s)
PASS
ok      command-line-arguments  0.300s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值