Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现。

net/http介绍

Go语言内置的net/http包提供了HTTP客户端和服务端的实现。

HTTP协议

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。

HTTP客户端

基本的HTTP/HTTPS请求

Get、Head、Post和PostForm函数发出HTTP/HTTPS请求。

resp, err := http.Get("http://example.com/")
...
resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf)
...
resp, err := http.PostForm("http://example.com/form",
url.Values{"key": {"Value"}, "id": {"123"}})

程序在使用完response后必须关闭回复的主体。

resp, err := http.Get("http://example.com/")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
// ...

[GET]

package main

import (
"fmt"
"io/ioutil"
"net/http"
) func main() {
resp, err := http.Get("https://www.liwenzhou.com/")
if err != nil {
fmt.Printf("get failed, err:%v\n", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("read from resp.Body failed, err:%v\n", err)
return
}
fmt.Print(string(body))
}

带参数:

参数需要使用到net/url来处理

func main() {
apiUrl := "http://127.0.0.1:9090/get"
// URL param
data := url.Values{}
data.Set("name", "mi")
data.Set("age", "18")
u, err := url.ParseRequestURI(apiUrl)
if err != nil {
fmt.Printf("parse url requestUrl failed, err:%v\n", err)
}
u.RawQuery = data.Encode() // URL encode
fmt.Println(u.String())
resp, err := http.Get(u.String())
if err != nil {
fmt.Printf("post failed, err:%v\n", err)
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("get resp failed, err:%v\n", err)
return
}
fmt.Println(string(b))
}

带header头部信息:

import (
"net/http"
) url := "https://b959e645-00ae-4bc3-8a55-7224d08b1d91.mock.pstmn.io/user/1" req, _ := http.NewRequest("GET", url, nil) req.Header.Add("Authorization", "xxxx") response, err := http.DefaultClient.Do(req)

对应server端:

func getHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
data := r.URL.Query()
fmt.Println(data.Get("name"))
fmt.Println(data.Get("age"))
answer := `{"status": "ok"}`
w.Write([]byte(answer))
}

[POST]

package main

import (
"fmt"
"io/ioutil"
"net/http"
"strings"
) // net/http post demo func main() {
url := "http://127.0.0.1:9090/post"
// 表单数据
//contentType := "application/x-www-form-urlencoded"
//data := "name=mi&age=18"
// json
contentType := "application/json"
data := `{"name":"mi","age":18}`
resp, err := http.Post(url, contentType, strings.NewReader(data))
if err != nil {
fmt.Printf("post failed, err:%v\n", err)
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("get resp failed, err:%v\n", err)
return
}
fmt.Println(string(b))
}

PostForm方式

func httpPostForm() {
resp, err := http.PostForm("http://www.01happy.com/demo/accept.php", url.Values{"key": {"Value"}, "id": {"123"}}) if err != nil { // handle error } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { // handle error } fmt.Println(string(body)) }

json:

func testPostJson() {
data := make(map[string]interface{})
data["site"] = "www.360.com"
data["name"] = "xxx"
bytesData, _ := json.Marshal(data)
resp, _ := http.Post("http://httpbin.org/post", "application/json", bytes.NewReader(bytesData))
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}

带有headers参数

func httpDo() {

    client := &http.Client{}

    req, err := http.NewRequest("POST", "http://www.01happy.com/demo/accept.php", strings.NewReader("name=cjb"))

    if err != nil {

        // handle error
} req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Cookie", "name=anny") resp, err := client.Do(req) defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil { // handle error
}
fmt.Println(string(body))
}

对应server端:

func postHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
// 1. 请求类型是application/x-www-form-urlencoded时解析form数据
r.ParseForm()
fmt.Println(r.PostForm) // 打印form数据
fmt.Println(r.PostForm.Get("name"), r.PostForm.Get("age"))
// 2. 请求类型是application/json时从r.Body读取数据
b, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Printf("read request.Body failed, err:%v\n", err)
return
}
fmt.Println(string(b))
answer := `{"status": "ok"}`
w.Write([]byte(answer))
}

自定义Client

要管理HTTP客户端的头域、重定向策略和其他设置,创建一个Client:

client := &http.Client{
CheckRedirect: redirectPolicyFunc,
}
resp, err := client.Get("http://example.com")
// ...
req, err := http.NewRequest("GET", "http://example.com", nil)
// ...
req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)

自定义Transport

要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport:

tr := &http.Transport{
TLSClientConfig: &tls.Config{RootCAs: pool},
DisableCompression: true,
}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://example.com")

Client和Transport类型都可以安全的被多个goroutine同时使用。出于效率考虑,应该一次建立、尽量重用。

服务端

默认的Server

ListenAndServe使用指定的监听地址和处理器启动一个HTTP服务端。处理器参数通常是nil,这表示采用包变量DefaultServeMux作为处理器。

Handle和HandleFunc函数可以向DefaultServeMux添加处理器。

http.Handle("/foo", fooHandler)
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
log.Fatal(http.ListenAndServe(":8080", nil))

默认的Server示例

使用Go语言中的net/http包来编写一个简单的接收HTTP请求的Server端示例,net/http包是对net包的进一步封装,专门用来处理HTTP协议的数据。具体的代码如下:

package main

import (
"fmt"
"net/http"
) func sayHello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello shanghai!")
} func main() {
http.HandleFunc("/", sayHello)
err := http.ListenAndServe(":9090", nil)
if err != nil {
fmt.Printf("http server failed, err:%v\n", err)
return
}
}

将上面的代码编译之后执行,打开你电脑上的浏览器在地址栏输入127.0.0.1:9090回车

自定义Server

要管理服务端的行为,可以创建一个自定义的Server:

s := &http.Server{
Addr: ":8080",
Handler: myHandler,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(s.ListenAndServe())

demo:

package main

import (
"encoding/json"
_"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
) var (
api = "http://xxxxx.com"
token = "9adf92861"
) type Result struct {
Code int `json:"code"`
Msg string `json:"msg"`
} type Resp struct {
Code string `json:"code"`
Msg string `json:"msg"`
} func wechatUrlHandle(w http.ResponseWriter, r *http.Request){
// 获取链接地址
var wechatUrl string
values := r.URL.Query()
wechatUrl = values.Get("url")
// 验证URL的正确性
targetUrl, err := url.ParseRequestURI(wechatUrl)
if err != nil {
fmt.Printf("parse url failed, err:%v\n", err)
}
fmt.Printf(fmt.Sprintf("url: %v", targetUrl)) // 拼接参数发起请求
data := fmt.Sprintf("token=%s&url=%s", token, targetUrl.String()) headers := "application/x-www-form-urlencoded"
res, err := http.Post(api, headers, strings.NewReader(data))
if err != nil {
fmt.Printf("post failed, err: %v\n", err)
return
} // 关闭请求资源
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil{
fmt.Fprintf(w, fmt.Sprintf("get resp failed. err: %v\n", err))
return
} var info Result
var ress Resp
w.Header().Set("Content-Type", "application/json")
if err := json.Unmarshal(body, &info); err == nil {
fmt.Println(info.Code, info.Msg)
ress.Code = "200"
ress.Msg = "Success"
t, _ := json.Marshal(ress)
w.Write(t)
}else{
ress.Code = "200"
ress.Msg = "failure"
t, _ := json.Marshal(ress)
fmt.Println("err: ", err)
w.Write(t)
}
} func main() { http.HandleFunc("/wechat/url", wechatUrlHandle)
err := http.ListenAndServe(":9090", nil) // 处理器参数一般未nil
if err != nil {
fmt.Printf("Http server failed. err: %v\n", err)
return
} }

Golang基础库之net/http的更多相关文章

  1. 如何使用gitlab自建golang基础库

    这里以go mod方式建立golang基础库 一.gitlab创建项目golib 地址为gitlab.xxx.com/base/golib 示例如下 go mod初始化命令 go mod init g ...

  2. golang 标准库间依赖的可视化展示

    简介 国庆看完 << Go 语言圣经 >>,总想做点什么,来加深下印象.以可视化的方式展示 golang 标准库之间的依赖,可能是一个比较好的切入点.做之前,简单搜了下相关的内 ...

  3. GoLang基础数据类型--->字典(map)详解

    GoLang基础数据类型--->字典(map)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   可能大家刚刚接触Golang的小伙伴都会跟我一样,这个map是干嘛的,是 ...

  4. cocos2d-x开发:服务端基础库封装

    元旦前面几天都在忙着面试,随后的几天也就一直在做服务端基础库开发方面的工作.对于服务端开发,是很久之前的事情了.那时候我还在大学读书,一直都是在倒腾服务端开发方面的东西,毕业后参加公司工作就是一直从事 ...

  5. golang基础之工程结构

    Golang 工作空间 编译工具对源码目录有严格要求,每个工作空间 (workspace) 必须由 bin.pkg.src 三个目录组成. workspace | +--- bin // go ins ...

  6. Golang 标准库log的实现

      原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1406905 前 ...

  7. Golang 基础之基础语法梳理 (三)

    大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第三章节 Golang 基础之基础语法梳理 (一) Gol ...

  8. Golang 基础之基础语法梳理 (一)

    大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第一章节 Golang 基础之基础语法梳理 (一) Gol ...

  9. F#之旅5 - 小实践之下载网页(爬虫基础库)

    参考文章:https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/posts/fvsc-download.html 参考的文章教了我们如 ...

  10. golang基础知识之encoding/json package

    golang基础知识之json 简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式.可以去json.org 查看json标准的清晰定义.json pack ...

随机推荐

  1. 声明式 Shadow DOM:简化 Web 组件开发的新工具

    在现代 Web 开发中,Web 组件已经成为创建模块化.可复用 UI 组件的标准工具.而 Shadow DOM 是 Web 组件技术的核心部分,它允许开发人员封装组件的内部结构和样式,避免组件的样式和 ...

  2. uniCloud

    https://doc.dcloud.net.cn/uniCloud/ 什么是uniCloud uniCloud推出了opendb,包含了大量的开源数据库模板,常见数据表无需自己设计 uniCloud ...

  3. 软件测试之Docker常见问题汇总!附解决方法!

    1.配置国内源进行docker安装,报错 HTTP Error 404 - Not Found 原因: 由于配置国内镜像源时,把地址写错了,导致后面安装docker提示HTTP Error 404 解 ...

  4. HttpURLConnection和HttpClient使用

    HttpURLConnection 这是Java的标准类,继承自URLConnection,可用于向指定网站发送GET/POST请求. 方法描述 void setRequestMethod(Strin ...

  5. Rust字符串类型全解析

    字符串是每种编程语言都绕不开的类型, 不过,在Rust中,你会看到远比其他语言更加丰富多样的字符串类型. 如下图: 为什么Rust中需要这么多种表示字符串的类型呢? 初学Rust时,可能无法理解为什么 ...

  6. 【赵渝强老师】MySQL高可用架构:MHA

    MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL 主从复制架构提供了 automating master failover 功能.MHA 在监控到 master 节 ...

  7. 【赵渝强老师】使用MongoDB的Web控制台

    MongoDB可以通过web界面监控数据库,默认情况下该选项是关闭的,需要在启动的时候开启.启用web 控制台,需要在启动mongodb的时候,加上:--httpinterface 启动MongoDB ...

  8. 称骨算命免费api接口_json数据接口示例_八字称骨测算程序php接口

    称骨算命是算命方法的一种,和生辰八字算命.紫微斗数算命异曲同工,略有不同,虽然都是用出生的时间算命,但比较而言,称骨算命将命运分的比较粗略,只是把命运分为五十一种.故对命运的考察不细致,不太准确,可以 ...

  9. 墨天轮最受DBA欢迎的数据库技术文档-监控篇

    好久不见,<墨天轮最受欢迎的技术文档>系列文章回归啦!本期主题数据库监控篇,希望能够帮助到大家!此外,为感谢大家支持,原文文末也给大家带来了返场福利,欢迎大家进入原文参与~ 数据库监控是许 ...

  10. dotnet实现多态的三种方法

    虚方法 virual 抽象方法 abstract 不能 new  不带方法体: 接口 Interface