前言

先说一下为什么要搞这个小东西?

米攸服务端前期主要是基于 Go 构建的,版本迭代过程中,业务复杂度不断增加,再加上中员团队有人员变动,考虑到目前团队的技术背景,我们开始考虑把接口服务分批迁移到 Java,开发效率和可控程度更高一些。其中有一些接口服务涉及周边模块较多,迁移的时间成本较高,我们决定暂时继续维护这些接口。后续接口需要升级时,如果变动较小,我们直接修改 Go 代码;如果变动较大,我们在 Go 代码中使用 HTTP 的方式调用 Java 接口实现,相当于给原有接口加了一个 钩子。为了减化接口调用代码编写的复杂度,我们考虑在 Go 代码中内置两个工具函数:GetPost,方便调用 Java 接口。

本文重点讨论 Get 和 Post 函数实现的关键细节,并给出核心代码。

Result

Java 接口的返回结果是一个 固定格式Json 字符串:

  • id

    请求ID,字符串。

  • code

    状态码,整数。

  • msg

    状态信息,字符串。

  • data

    数据,任意类型。

我们使用 结构体 封装返回结果:

  type Result struct {
Id string `json:"id"`
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}

可以发现,结构体的字段名称和返回结果的字段名称是不一样的(首字母大小写),两者相互转换的时候名称会对应不上,需要在结构体中使用类似 `json:"id"` 的声明,把结构体中的字段名称和返回结果的字段名称一一对应起来。

特别注意:声明字段名称时标点符号的使用。

Client

Go 提供的 Http 客户端(Client)实例是线程安全的,一个进程内只需要有一个即可:

  var client = http.Client{}

Get

Get 函数的参数应该有两个:接口路径(url)和 接口参数(params)。接口路径比较简单,就是一个字符串(string),我们主要讨论接口参数。

我们使用 Query String 的方式传递 Get 参数,如:/interface/param1=value1&param2=value2,接口参数的类型应该是一个内部包含多个键值对的 字典(map[string]interface{}),键名称是参数名称,键值是参数值;考虑到实际使用场景,参数值的类型限制为三种:

  • string
  • int
  • float64

因为参数的值类型是不确定的,所以使用 interface{} 表示任意类型,函数内部判断具体类型。

因为调用接口时需要添加 请求头请求参数,所以不能直接使用 http.Get 这样的简化函数,实现流程:

创建请求

使用 http.NewRequest 创建请求:

  req, err := http.NewRequest("GET", url, nil)

添加请求头

设置请求响应的内容类型为 json:

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

设置调用接口时的 Token:

  req.Header.Add("token", MEETU_API_TOKEN)

添加请求参数

创建请求参数:

  query := req.URL.Query()

逐个添加请求参数:

 query.Add(name, value)

注意:添加请求参数时,name(参数名称) 和 value(参数类型) 类型都是字符串。

如前文所述,接口参数是一个字典类型的变量,我们需要遍历这个变量中的每一个键值对,逐个添加参数。遍历可以使用 Range

  for name, value := range params {
...
}

如前文所述,参数值类型是有限制的,遍历过程中,我们需要判断参数值类型是否符合要求。类型判断可以使用 value.(type)

  switch value.(type) {
case string:
query.Add(name, value.(string)) case int:
query.Add(name, strconv.Itoa(value.(int))) case float64:
query.Add(name, strconv.FormatFloat(value.(float64), 'f', -1, 64)) default:
return Result{}, errors.New("params type only support string, int and float64")
}

使用 value.(string)、value.(int) 和 value.(float64) 把变量 value(类型:interface{}) 分别转换为类型 string、int 和 float64 的变量。使用 strconv.Itoa 把 int 变量转换为 string 变量,使用 strconv.FormatFloat 把 float64 变量转换为 string 变量。

请求参数值可能包含特殊字符,需要转义:

  req.URL.RawQuery = query.Encode()

请求参数添加完成。

执行请求,获取结果

  resp, err := client.Do(req)

  defer resp.Body.Close()

defer 表示 Get 函数执行完成之后,关闭 Http 客户端内部的网络连接。

解析结果

响应体(resp.Body)的数据是字节流,需要解码并反序列化成类型为 Result 的变量 result:

  json.NewDecoder(resp.Body).Decode(&result)

返回结果

  return result, nil

到此,Get 函数实现完成,代码如下:

  func Get(url string, params map[string]interface{}) (Result, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return Result{}, err
} req.Header.Add("Content-Type", "application/json")
req.Header.Add("token", MEETU_API_TOKEN) if params != nil {
query := req.URL.Query() for name, value := range params {
switch value.(type) {
case string:
query.Add(name, value.(string)) case int:
query.Add(name, strconv.Itoa(value.(int))) case float64:
query.Add(name, strconv.FormatFloat(value.(float64), 'f', -1, 64)) default:
return Result{}, errors.New("params type only support string, int and float64")
}
} req.URL.RawQuery = query.Encode()
} resp, err := client.Do(req)
if err != nil {
return Result{}, err
} defer resp.Body.Close() var result Result err = json.NewDecoder(resp.Body).Decode(&result)
if err != nil {
return Result{}, err
} return result, nil
}

Post

Post 函数的实现过程整体和 Get 是类似的,唯一不同的就是请求参数的处理。我们使用 Body 传递 Post 参数。

其余内容请参考:Go Http Get 和 Post 工具函数

Go Http Get 和 Post 工具函数的更多相关文章

  1. JQuery中的工具函数总结

    前提引入 前提当然也是要引入Jquery啦... <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js" typ ...

  2. 五、jquery使用工具函数

    工具函数对应的网址在 http://api.jquery.com/categouy/utilities/   工具函数处理对象的不同,可以将其分为几大类别:浏览器的检测.数组和对象的操作.字符串的操作 ...

  3. jQuery工具函数(转)

    原文地址:http://www.cnblogs.com/kissdodog/archive/2012/12/27/2835561.html 作者:逆心 ------------------------ ...

  4. jQuery实用工具函数

    1. 什么是工具函数 在jQuery中,工具函数是指直接依附于jQuery对象.针对jquery对象本身定义的说法,即全局性的函数,我们统称为工具函数,或Utilities函数.它们有一个明显的特征, ...

  5. javascript工具函数

    第一部分 JavaScript工具函数 转义特殊字符为html实体   HtmlEncode: function(str){ return str.replace(/&/g, '&') ...

  6. 读<jQuery 权威指南>[6]--实用工具函数

    官方地址:http://api.jquery.com/category/utilities/ 一.数组和对象操作 1. $.each——遍历 $.each(obj,function(param1,pa ...

  7. AJAX编程-封装ajax工具函数

    即 Asynchronous [e'sɪŋkrənəs] Javascript And XML,AJAX 不是一门的新的语言,而是对现有技术的综合利用.本质是在HTTP协议的基础上以异步的方式与服务器 ...

  8. JQ工具函数

    在jQuery中,工具函数是指直接依附于jQuery对象,针对jQuery对象本身定义的方法,即全局性的,我们统称为工具函数,或Utilites函数 主要作用于:字符串.数组.对象 API:工具函数 ...

  9. jquery源码分析-工具函数

    jQuery的版本一路狂飙啊,现在都到了2.0.X版本了.有空的时候,看看jquery的源码,学习一下别人的编程思路还是不错的. 下面这里是一些jquery的工具函数代码,大家可以看看,实现思路还是很 ...

  10. jQuery工具函数

    要点:1.字符串操作2.数组和对象操作3.测试操作4.URL 操作5.浏览器检测6.其他操作 工具函数是指直接依附于 jQuery 对象,针对 jQuery 对象本身定义的方法,即全局性的函数.它的作 ...

随机推荐

  1. 学习zabbix(三)

    前言: 学习zabbix之前,不得不了解的是SNMP协议 SNMP:简单网络管理协议(Simple Network Protocol) Snmp由两部分组成,监控端和被监控端 监控模式: 主动模式:N ...

  2. three模型高亮外发光效果

    页面效果如下: vue3+three完整代码如下: <template> </template> <script setup> import * as THREE ...

  3. git 泄露(Log、Stash、Index)svn泄露

    Git泄露 Log 首先介绍下.git:Git泄露:当前大量开发人员使用git进行版本控制,对站点自动部署.如果配置不当,可能会将.git文件夹直接部署到线上环境.这就引起了git泄露漏洞. 首先使用 ...

  4. 每日所学之自学习大数据的Linux环境的配置

    今天开始配置环境,因为下载镜像文件需要很长时间,加上训练,所以Linux环境之配置了一半 VMware下载及安装教程(Window) 在安装虚拟机时需要下载镜像文件 下面是我下载的镜像文件的地址 Ce ...

  5. Android设置TextView为不可见

    通常控件的可见与不可见分为三种情况. 第一种    gone         表示不可见并且不占用空间 第二种    visible       表示可见 第三种    invisible    表示 ...

  6. mixin和composition api

    1. 这两个都是实现组件逻辑复用的法宝 2. composition api是vue3的,  composition api的出现就是解决mixins的不足之处的 一. mixin 回顾下mixin, ...

  7. 圆桌killer

    [问题描述] 圆桌上围坐着2n个人.其中n个人是好人,另外n个人是坏人.如果从第m(m<=2n)个人开始数数,数到第k个人,则立即处死该人:然后从被处死的人之后重新开始数数,再将数到的第k个人处 ...

  8. 搭建Vue小页面

    学习链接:https://blog.csdn.net/zhenzuo_x/article/details/81013475 环境搭建: 浏览器:Chrome IDE:VS Code或者WebStorm ...

  9. Python入门-面向对象三大特性-封装

    一.封装 封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容. 所以,在使用面向对象的封装特性时,需要: 将内容封装到某处 从某处调用被封装的内容 第一步:将内容封装到某处 sel ...

  10. spring-bean依赖注入-03

    set注入:set注入地址 通过构造方法进行注入 1.创建UserDao接口以及UserDaoImpl实现类(接口代码省略) public class UserDaoImpl implements U ...