Golang基础库之net/http
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的更多相关文章
- 如何使用gitlab自建golang基础库
这里以go mod方式建立golang基础库 一.gitlab创建项目golib 地址为gitlab.xxx.com/base/golib 示例如下 go mod初始化命令 go mod init g ...
- golang 标准库间依赖的可视化展示
简介 国庆看完 << Go 语言圣经 >>,总想做点什么,来加深下印象.以可视化的方式展示 golang 标准库之间的依赖,可能是一个比较好的切入点.做之前,简单搜了下相关的内 ...
- GoLang基础数据类型--->字典(map)详解
GoLang基础数据类型--->字典(map)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 可能大家刚刚接触Golang的小伙伴都会跟我一样,这个map是干嘛的,是 ...
- cocos2d-x开发:服务端基础库封装
元旦前面几天都在忙着面试,随后的几天也就一直在做服务端基础库开发方面的工作.对于服务端开发,是很久之前的事情了.那时候我还在大学读书,一直都是在倒腾服务端开发方面的东西,毕业后参加公司工作就是一直从事 ...
- golang基础之工程结构
Golang 工作空间 编译工具对源码目录有严格要求,每个工作空间 (workspace) 必须由 bin.pkg.src 三个目录组成. workspace | +--- bin // go ins ...
- Golang 标准库log的实现
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1406905 前 ...
- Golang 基础之基础语法梳理 (三)
大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第三章节 Golang 基础之基础语法梳理 (一) Gol ...
- Golang 基础之基础语法梳理 (一)
大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第一章节 Golang 基础之基础语法梳理 (一) Gol ...
- F#之旅5 - 小实践之下载网页(爬虫基础库)
参考文章:https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/posts/fvsc-download.html 参考的文章教了我们如 ...
- golang基础知识之encoding/json package
golang基础知识之json 简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式.可以去json.org 查看json标准的清晰定义.json pack ...
随机推荐
- .net core 依赖注入,运行报错 Cannot consume scoped 'xxx' service from singleton 'yyy'
这是因为 xxx 的生命周期是 AddScoped 注入的,而 yyy 的生命周期是 AddSingleton ,然后 yyy 这个单例的对象中,它又依赖了xxx 也就是说,单例注入的对象中依赖了 A ...
- Authentication vs. Authorization
Authentication vs. Authorization So, what is the difference between authentication and authorization ...
- EasyDarwin,EasyNVR, EasyNVS, EasyDSS...这些都是啥
EasyDarwin 是开源的基础版本, 其他都是衍生产品(http://www.easydarwin.org/) EasyNVR, 就是视频监控录像机,可以查看实时监控和保存监控视频, 如下图, ( ...
- HashMap深入讲解
HashMap是Java中最常用的集合类框架,也是Java语言中非常典型的数据结构, 而HashSet和HashMap者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说HashSet ...
- Angular 16+ 高级教程 – 谈谈 ASP.NET Core & Angular & React 在业务开发上各自的优势和体验
前言 日常, 我的开发都围绕着 ASP.NET Core 和 Angular. 这篇想聊聊它们各自的特点和解决问题的方式. 以及最重要的, 我们该在什么时候采用何种方案更为妥当. 浅谈项目分类 我一般 ...
- grid网格布局
https://ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html Grid 布局只对项目生效 划分网格的线,称为"网格线" ...
- 运输小猫娘之再续 5k 传奇之寻找人道主义素数
原文 前情提要 本章主角 5k_sync_closer 第一章 从再续前缘到苦心寻找满足最优条件的人道主义美丽素数 上回书说到,5k 因为拯救大家被炸断了 \(1000000007\) 米中的十五千米 ...
- “全栈合一 智慧运维”智和网管平台SugarNMS V9版本发布
以"管控万物 无所不能 无处不"在为产品创新理念,智和信通打造"全栈式"网络安全运维平台-智和网管平台SugarNMS.立足数字化.智能化.可视化.自动化,整合 ...
- typeof typeof 'texs'是什么类型
typeof '12' 返回 'string' 是字符串类型 :
- Linux的Terminal调用不出来,一直转圈圈
后来发现是环境变量的问题 [oracle@ora19rac01 ~]$ cat .bash_profile # .bash_profile # Get the aliases and function ...