【Golang 接口自动化02】使用标准库net/http发送Post请求

news2024/11/15 16:36:15

目录

写在前面

发送Post请求

示例代码

源码分析

Post请求参数解析

响应数据解析

验证

发送Json/XMl

Json请求示例代码

xml请求示例代码

总结

资料获取方法


写在前面

上一篇我们介绍了使用 net/http 发送get请求,因为考虑到篇幅问题,把Post单独拎了出来,我们在这一篇一起从源码来了解一下Golang的Post请求。

发送Post请求

net/http发送Post请求很容易,下面的代码我们和Get请求一样,把响应的内容的信息打印出来了,细心的朋友可能会发现,在参数传递、和结果解析时用了三种不同的方式,我们将在后面进行解析。

示例代码

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"reflect"
	"strings"
)

func main() {
	resp, err := http.Post("http://httpbin.org/post",
		"application/x-www-form-urlencoded",
		strings.NewReader("name=Detector&mobile=1xxxxxxxx"))
	if err != nil {
		fmt.Println(err)
		return
	}

	defer resp.Body.Close()
	headers := resp.Header
	// headers 打印报文头部信息
	for k, v := range headers {
		fmt.Printf("%v, %v\n", k, v) // %v 打印interfac{}的值
	}

	// 打印响应信息内容
	fmt.Printf("响应状态:%s,响应码: %d\n", resp.Status, resp.StatusCode)
	fmt.Printf("协议:%s\n", resp.Proto)
	fmt.Printf("响应内容长度: %d\n", resp.ContentLength)
	fmt.Printf("编码格式:%v\n", resp.TransferEncoding) // 未指定时为空
	fmt.Printf("是否压缩:%t\n", resp.Uncompressed)
	fmt.Println(reflect.TypeOf(resp.Body)) // *http.gzipReader
	fmt.Println(resp.Body)

	buf := bytes.NewBuffer(make([]byte, 0, 512))
	length, _ := buf.ReadFrom(resp.Body)
	fmt.Println(len(buf.Bytes()))
	fmt.Println(length)
	fmt.Println(string(buf.Bytes()))
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(body))
}

源码分析

Post请求参数解析

我们首先来看一下C:\Go\src\net\http\client.go中Post和Get请求的源码:

func Get(url string) (resp *Response, err error) {
	return DefaultClient.Get(url)
}
func Post(url string, contentType string, body io.Reader) (resp *Response, err error) {
	return DefaultClient.Post(url, contentType, body)
}

从上面的定义可以看出,Post请求的参数比Get复杂一些,不仅要传递string类型contentType还有传递io.Reader类型的body体。可能有的小伙伴就有疑问了-- io.Reader类型的body体是不是意味着我们一定要使用io.Reader模块来获取数据呢?

答案当然是否定的。

我们通过阅读源码,来找想要的答案。

找到其最小粒度的接口是一个比较好的手段,io.Reader最小粒度的接口的定义在C:\Go\src\io\io.go中:

type Reader interface {
	Read(p []byte) (n int, err error)
}

在我前面的一篇博客【Golang】基础10 Go语言最精妙的设计--interface中学习过 interface,其中有两句话是这样的:

interface类型定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了此接口。如果我们定义了一个interface的变量,那么这个变量里面可以存实现这个interface的任意类型的对象。

针对io.Reader的定义翻译一下就是,只要实现了Read(p []byte) (n int, err error)方法的类型,就可以存储io.Reader,从而作为Post请求的Body参数。

我们接着来看看响应resp中数据的定义。

响应数据解析

在上一篇我们对http请求中的数据进行了介绍,这一次我们针对resp.Body进行展开。

C:\Go\src\net\http\response.go中我们可以看到它的类型Body io.ReadCloser,在C:\Go\src\io\io.go中我们可以看到对应的定义是这样的:

type ReadCloser interface {
	Reader
	Closer
}

而Reader就是我们上面分析的过的请求body定义的Reader,而Closer是一个error类型:

type Closer interface {
	Close() error
}

根据我们上面的结论-- 定义的某个接口的变量可以存储同样实现该接口的任意类型对象,即是说任意类型,只要实现了 Reader和 Closer 即可以用来解析resp.Body

那我们来验证一下示例里面使用的三种方法是不是符合我们这个结论。

验证

  • strings.NewReader
    我们可以在C:\Go\src\strings\reader.go看到 Reader类型的 Read方法:

  • bytes.NewBuffer
    我们可以在C:\Go\src\bytes\buffer.go看到 Buffer类型的 Read方法:

  • ioutil.ReadAll
    我们可以在C:\Go\src\io\ioutil\ioutil.go看到 io.Reader类型的 ReadAllClose() error方法:

发送Json/XMl

在了解了上面的知识之后,我们再来看发送Json、XML数据等就比较简单了。

Json请求示例代码

func JsonReq() {
	info := make(map[string]interface{})
	info["name"] = "Detector"
	info["age"] = 15
	info["loc"] = "深圳"
	// 将map解析未[]byte类型
	bytesData, _ := json.Marshal(info)
	// 将解析之后的数据转为*Reader类型
	reader := bytes.NewReader(bytesData)
	println(reader)
	resp, _ := http.Post("http://httpbin.org/post",
		"application/json",
		reader)
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body))
}

代码里面给了一些注释,我们把要发送的数据转化为了 *Reader类型,然后就可以直接发送了。(我们从上面的源码分析可以知道这个类型是可以存储io.Reader的数据的)

xml请求示例代码

func XMLReq() {
	xml := `<?xml version="1.0" encoding="UTF-8"?>
	<resources>
		<string name="VideoLoading">Loading video…</string>
		<string name="ApplicationName">what</string>
	</resources>`
	bytesData := strings.NewReader(xml)
	resp, _ := http.Post("http://httpbin.org/post",
		"application/xml",
		bytesData)
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body))
}

总结

  • Json、xml请求
  • 请求、响应数据简析
  • interface概念复习

资料获取方法

【留言777】

各位想获取源码等教程资料的朋友请点赞 + 评论 + 收藏,三连!

三连之后我会在评论区挨个私信发给你们~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/811646.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试真题 Java 实现【输出指定字母在字符串的中的索引】【2023 B卷 100分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述说明&#xff1a; 四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#x…

四年前没做成的跑腿代驾平台,四年后再做也许就成了

​几年前新零售概念大火&#xff0c;不止是传统门店商家蠢蠢欲动&#xff0c;很多传统行业都在试图搭上互联网的快车&#xff0c;在传统实体中脱颖而出。当时炒的最热的除了社区团购、智慧门店就是同城跑腿、搬家、拉货、代驾代买这类服务型了。 社区团购几乎是各家杀的头破血流…

Zabbix分布式监控快速入门

目录 1 Zabbix简介1.1 软件架构1.2 版本选择1.3 功能特性 2 安装与部署2.1 时间同步需求2.2 下载仓库官方源2.3 Zabbix-Server服务端的安装2.3.1 安装MySQL2.3.1.1 创建Zabbix数据库2.3.1.2 导入Zabbix库的数据文件 2.3.2 配置zabbix_server.conf2.3.3 开启Zabbix-Server服务2.…

Day47 算法记录|动态规划14子序列

子序列 1143. 最长公共子序列1035.不相交的线53. 最大子数组和 1143. 最长公共子序列 这道题和718. 最长重复子数组的区别&#xff1a;这道题的子序列可以不连续 这个视频讲解的很好 class Solution {public int longestCommonSubsequence(String text1, String text2) {char…

打开域名跳转其他网站,官网被黑解决方案(Linux)

某天打开网站&#xff0c;发现进入首页&#xff0c;马上挑战到其他赌博网站。 事不宜迟&#xff0c;不能让客户发现&#xff0c;得马上解决 我的网站跳转到这个域名了 例如网站跳转到 k77.cc 就在你们部署的代码的当前文件夹下面&#xff0c;执行下如下命令 find -type …

SQL-每日一题【1075. 项目员工 I】

题目 项目表 Project&#xff1a; 员工表 Employee&#xff1a; 请写一个 SQL 语句&#xff0c;查询每一个项目中员工的 平均 工作年限&#xff0c;精确到小数点后两位。 查询结果的格式如下&#xff1a; 解题思路 前置知识 AVG 函数 定义和用法&#xff1a; AVG 函数返回数…

基于ARM+FPGA (STM32+ Cyclone 4)的滚动轴承状态监测系统

状态监测系统能够在故障早期及时发现机械设备的异常状态&#xff0c;避免故障的 进一步恶化造成不必要的损失&#xff0c;滚动轴承是机械设备的易损部件&#xff0c;本文对以滚动 轴承为研究对象的状态监测系统展开研究。现有的监测技术多采用定时上传监 测数据&#xff0c;…

【Spring AOP + 自定义注解 + 数据源 实现主从库切换读写分离】—— 案例实战

&#x1f4a7; S p r i n g A O P 主从数据源切换 读写分离 自定义注解案例实战&#xff01; \color{#FF1493}{Spring AOP 主从数据源切换 读写分离 自定义注解 案例实战&#xff01;} SpringAOP主从数据源切换读写分离自定义注解案例实战&#xff01;&#x1f4a7; …

提升开发效率,Lombok的链式编程和构建模式

目录 链式编程 定义 代码示例 ​编辑 Accessors(chaintrue) 开启链式编程 ​编辑 Accessors(chain true,fluent true) 去除set和get 构建模式 定义 代码示例 ​编辑 踩坑 Singular 定义 代码示例 踩坑默认值情况 ​编辑 With 定义 代码示例 链式编程 定义 链…

SQL-每日一题【1070. 产品销售分析 III】

题目 销售表 Sales&#xff1a; 产品表 Product&#xff1a; 编写一个 SQL 查询&#xff0c;选出每个销售产品 第一年 销售的 产品 id、年份、数量 和 价格。 结果表中的条目可以按 任意顺序 排列。 查询结果格式如下例所示&#xff1a; 示例 1&#xff1a; 解题思路 前置知…

永恒之蓝复现(ms17-010)

目录标题 一、漏洞原理二、影响版本三、永恒之蓝复现复现环境复现过程1.主机发现 2.使用MSF的永恒之蓝漏洞模块3.使用ms17-010扫描模块&#xff0c;对win7进行扫描4.使用ms17-010攻击模块&#xff0c;对win7进行攻击5.得到win7权限6.通过shell对win7进行控制 一、漏洞原理 永恒…

第101章#远程调试西门子PLC(明牛智能网关)入门

一、下载明牛网站上的MNConfig&#xff08;用于配置MNGate系列产品&#xff09;。 二、注册账号。 三、用注册的账号登录MNConfig 四、在左侧BOX列表中,点击BOX列表—右键—添加BOX 五、选择联网方式&#xff0c;一般都是用的4G。 可以用自己的手机卡进行测试。 1、插入4G卡&am…

【Docker 那些事儿】如何安全地进入到容器内部

文章目录 &#x1f31f; 前言1. 容器运行&#x1f347; 自动重启的容器&#x1f347; 自定义名称的容器&#x1f347; 开启端口的容器&#x1f347; 与宿主机共享目录的容器 2. 进入容器2.1 容器的三种状态&#x1f351; 运行状态&#x1f351; 暂停状态&#x1f351; 终止状态…

操作系统4

文件管理 文件的逻辑结构 文件的目录 文件的物理结构 文件存储空间管理 文件的基本操作

stm32内存杂记

从上图中可以看出SRAM空间用来存放&#xff1a;1.各个文件中声明和定义的全局变量、静态数据和常量&#xff1b;2.未初始化的全局变量&#xff1b;3.HEAP区&#xff1b;4.STACK区 这是在.map文件中&#xff0c;双击工程target打开 堆栈是处于以0x2000xx地址处的 EQU伪代码&…

跟着《代码随想录》刷题(七)——回溯算法

7.1 组合问题 77、组合 LeetCode&#xff1a;77、组合 &#xff08;1&#xff09;未剪枝优化 class Solution { private:vector<vector<int>> result; // 存放符合条件结果的集合vector<int> path; // 用来存放符合条件结果void backtracking(int n, i…

SMB协议简单免费搭建个人winNAS

SMB协议&#xff0c;让PC变身小型winNAS&#xff0c;简单免费搭建个人winNAS 打开SMB服务设置共享文件夹远程连接 SMB 的优点之一是兼容性好&#xff0c;在各平台获得了广泛支持&#xff0c;包括 Windows、Linux、macOS 等各系统挂载访问都很方便。另外 SMB 也是各种电视、电视…

Arcgis通过模型构建器计算几何坐标

模型 模型中&#xff0c;先添加字段&#xff0c;再计算字段 计算字段 模型的计算字段中&#xff0c;表达式是类似这样写的&#xff0c;其中Xmin表示X坐标&#xff0c;Ymin表示Y坐标 !Shape.extent.Xmin!

免费商用 Meta 发布开源大语言模型 Llama 2

Meta 和微软深度合作&#xff0c;正式推出下一代开源大语言模型 Llama 2&#xff0c;并宣布免费提供给研究和商业使用。 Llama 2 论文地址&#xff1a;Llama 2: Open Foundation and Fine-Tuned Chat Models 据介绍&#xff0c;相比于 Llama 1&#xff0c;Llama 2 的训练数据多…

开源Blazor UI组件库精选:让你的Blazor项目焕然一新!

今天给大家推荐一些开源、美观的Blazor UI组件库&#xff0c;这些优秀的开源框架和项目不仅能够帮助开发者们提高开发效率&#xff0c;还能够为他们的项目带来更加丰富的用户体验。 注&#xff1a;排名不分先后&#xff0c;都是十分优秀的开源框架和项目 ​Ant Design Blazor…