Go Http Get 和 Post 工具函数
前言
先说一下为什么要搞这个小东西?
米攸服务端前期主要是基于 Go 构建的,版本迭代过程中,业务复杂度不断增加,再加上中员团队有人员变动,考虑到目前团队的技术背景,我们开始考虑把接口服务分批迁移到 Java,开发效率和可控程度更高一些。其中有一些接口服务涉及周边模块较多,迁移的时间成本较高,我们决定暂时继续维护这些接口。后续接口需要升级时,如果变动较小,我们直接修改 Go 代码;如果变动较大,我们在 Go 代码中使用 HTTP 的方式调用 Java 接口实现,相当于给原有接口加了一个 钩子。为了减化接口调用代码编写的复杂度,我们考虑在 Go 代码中内置两个工具函数:Get 和 Post,方便调用 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¶m2=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 工具函数的更多相关文章
- JQuery中的工具函数总结
		
前提引入 前提当然也是要引入Jquery啦... <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js" typ ...
 - 五、jquery使用工具函数
		
工具函数对应的网址在 http://api.jquery.com/categouy/utilities/ 工具函数处理对象的不同,可以将其分为几大类别:浏览器的检测.数组和对象的操作.字符串的操作 ...
 - jQuery工具函数(转)
		
原文地址:http://www.cnblogs.com/kissdodog/archive/2012/12/27/2835561.html 作者:逆心 ------------------------ ...
 - jQuery实用工具函数
		
1. 什么是工具函数 在jQuery中,工具函数是指直接依附于jQuery对象.针对jquery对象本身定义的说法,即全局性的函数,我们统称为工具函数,或Utilities函数.它们有一个明显的特征, ...
 - javascript工具函数
		
第一部分 JavaScript工具函数 转义特殊字符为html实体 HtmlEncode: function(str){ return str.replace(/&/g, '&') ...
 - 读<jQuery 权威指南>[6]--实用工具函数
		
官方地址:http://api.jquery.com/category/utilities/ 一.数组和对象操作 1. $.each——遍历 $.each(obj,function(param1,pa ...
 - AJAX编程-封装ajax工具函数
		
即 Asynchronous [e'sɪŋkrənəs] Javascript And XML,AJAX 不是一门的新的语言,而是对现有技术的综合利用.本质是在HTTP协议的基础上以异步的方式与服务器 ...
 - JQ工具函数
		
在jQuery中,工具函数是指直接依附于jQuery对象,针对jQuery对象本身定义的方法,即全局性的,我们统称为工具函数,或Utilites函数 主要作用于:字符串.数组.对象 API:工具函数 ...
 - jquery源码分析-工具函数
		
jQuery的版本一路狂飙啊,现在都到了2.0.X版本了.有空的时候,看看jquery的源码,学习一下别人的编程思路还是不错的. 下面这里是一些jquery的工具函数代码,大家可以看看,实现思路还是很 ...
 - jQuery工具函数
		
要点:1.字符串操作2.数组和对象操作3.测试操作4.URL 操作5.浏览器检测6.其他操作 工具函数是指直接依附于 jQuery 对象,针对 jQuery 对象本身定义的方法,即全局性的函数.它的作 ...
 
随机推荐
- 哪些是重要的 bean 生命周期方法?你能重载它们吗?
			
有两个重要的 bean 生命周期方法,第一个是 setup , 它是在容器加载 bean 的时候被调用.第二个方法是 teardown 它是在容器卸载类的时候被调用. The bean 标签有两个重要 ...
 - C语言之main方法解析(知识点1)
			
1.注释 /*自带注释*/2.引包 #include <stdio.h>3.主方法 void main{}4.执行体 printf("打印& ...
 - 51单片机头文件reg51.h详解
			
转自:http://www.51hei.com/mcu/2670.html 我们在用c语言编程时往往第一行就是头文件,51单片机为reg51.h或reg52.h,51单片机相对来说比较简单,头文件里面 ...
 - 顺利通过EMC实验(14)
 - Kurento安装与入门08——Group Call
			
Group Call 本示例展示了一个视频聊天室的功能,不同的聊天室之间互相隔离. 官网文档 Group Call 首先从github上获取代码(如果已经获取可以跳过,获取的代码已经包括后面的示例代码 ...
 - 手把手教你打造一个纯CSS图标库
			
来,干了这碗安利 写这篇文章的目的其实就是为了安利一下我的图标库:iconoo,所以,开门见山,star吧少年少妇们!(这样的我是不是应该要加个github互粉的团伙了?) 主题说完了,下面进入正题. ...
 - 让我为你介绍一个神器:Chimee,一套可扩展的 H5 视频播放器解决方案
			
Chimee(读"奇米", [tʃɪ'mɪ:])是由奇舞团开源的一套 H5 视频播放器解决方案,由奇舞团视频云前端团队结合在业务和视频编解码方向的沉淀积累倾心打造. Chimee ...
 - js和原生应用常用的数据交互方式
			
场景1 在原生app中经常会使用到H5页面,比如说电商中的活动页,一些电商中的详情页,等等...这些页面都有一个特点,那就是在未来修改的可能性,和一次性的几率特别的大.所以用H5的页面是最睿智的一种选 ...
 - vue中执行npm run build报错解决方法?
			
遇到了执行npm run build 后报错: [build:js ] Module not found: Error: Can't resolve 'scss-loader' in 'D:\work ...
 - vscode快速生成html的基本代码
			
转载自:https://blog.csdn.net/suwyer/article/details/81237880 在vscode里新建html文件, 总是要一行一行的写标准的html代码: 而DW新 ...