栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

Golang - net/http 笔记

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Golang - net/http 笔记

Server
package main

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

// 模拟实现 Handler 接口
type Bar struct {}

func (b Bar) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	tgt := req.URL.Query().Get("name")
	fmt.Fprintf(w, "Hi %v", tgt)
}

func main() {
    // 创建路由, 方式 1: Handle(), 参数是 Handle 接口
	http.Handle("/bar", Bar{})

    // 创建路由, 方式 2: HandleFunc(), 参数是满足要求的 func()
	http.HandleFunc("/foo", func(w http.ResponseWriter, req *http.Request) {
		tgt := req.URL.Query().Get("name")
		fmt.Fprintf(w, "Hello %v", tgt)
	})

    // 启动服务, log.Fatal() 输出错误信息并退出
	log.Fatal(http.ListenAndServe(":9999", nil))
}

Client 发起请求 GET 直接请求
// 发起请求
rep, err := http.Get("http://127.0.0.1:9998/sayhello")

// 这里做一个处理 err 的示例, 文档中其他位置都忽略错误处理
if err != nil {
    log.fatel(err)
}

// 这个很重要, 回收资源
defer rep.Body.Close()
自定义请求
// client
c := http.DefaultClient //  实际实现 c := &http.Client{}

// request
req, _ := http.NewRequest("GET", "http://127.0.0.1:9998/x", nil)

// 加header
req.Header.Add("token", "xxx")  // Add, 如果变量不存在则设置, 如果存在则不设置
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")  // Set, 如果变量存在则设置, 不存在则不设置

// 加参数
req.URL.RawQuery = url.Values{
	"key": {"v"},
}.Encode()

// client 发送 request, 并且拿到返回
rep := c.Do(req)
defer rep.Body.Close()  // 回收资源

补充 两种 header 的设置方法
// 1. req.Header.Add(k, v)
req.Header.Add("token", "xxx")

// 2. 因为 Header 类型为 map[string][]string, 可以定义一个同类型的 Header 数据, 然后赋值
req.Header = map[string][]string{
	"token": {"xxx"},
	"num": {"1", "2", "3"},
}
两种参数的设置方法
// 1. req.URL.RawQuery = url.Values{}, 虽然 url.Values 类型也是 map[string][]string, 但是直接使用 map 则没有 Encode 方法, 不自找麻烦了
req.URL.RawQuery = url.Values{
	"key": {"v"},
}.Encode()

// 2. 使用 Sprinf 将参数拼接到 url 中
newURL := fmt.Sprintf("https://%v/$v?%v=$v", url, uri, k, v)

POST 直接请求
// http.Post 只能设置 url, contentType 和 body, 如果需要设置 header, 需要 http.DefaultClient
rep, err := http.Post("http://127.0.0.1:9998/y", "application/json", strings.NewReader("name=Tim"))

if err != nil {
	log.fatal(err)
}

defer rep.Body.Close()
自定义请求
// client
c := http.DefaultClient //  实际实现 c := &http.Client{}

// 模拟一个数据类型, 先进行序列化, 再将 []byte 转为 io.Reader
data := []int{1, 2, 3}
marshal, _ := json.Marshal(data)
body := bytes.NewReader(marshal)

// request
req, _ := http.NewRequest("POST", "http://127.0.0.1:9998/x", body)

// 加header
req.Header.Add("token", "xxx")  // 如果变量不存在则设置, 如果存在则不设置

// client 发送 request
rep := c.Do(req)
defer rep.Body.Close()

补充 两种 io.Reader 的获取方法(造 body)
// 1. []byte -> io.Reader, 需要先将 go 的数据类型序列化为 []byte
data := []int{1, 2, 3}
marshal, _ := json.Marshal(data)
body := bytes.NewReader(marshal)

// 2. string -> io.Reader
strings.NewReader("name=Tim"))

读取 response 数据 读所有
all, _ := ioutil.ReadAll(rep.Body)
根据字节分片读
r := make([]byte, 0, 1024)   // 结果
buf := make([]byte, 0, 128)  // 缓存

// 一直读, 读到出现 EOF 为止
for {
    // n 是读取的字节个数
    n, err := rep.Body.Read(buf)

    // 如果是 EOF 错误, n 为末尾的字节位置, 将 buf 切片并追加到 r 中, 返回
    if err == io.EOF {
        r = append(r, buf[:n]...)
       	break
    }

    // 如果有报错且报错不是 EOF, 则退出
    if err != nil && err != io.EOF {
        log.Println(err)
        break
    }

	// 为出现 EOF, 则将 buf 内所有内容全部追加到 r
    r = append(r, buf[:]...)
}

// 打印结果
fmt.Println(string(r))

取得结果
  • 强转
    // []byte --> string
    string(body)
    
  • 反序列化: json --> struct or map
  • 第三方包解析: 从 json 直接取值
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/906676.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号