首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

golang中实现通用http参数与结构体的转换

更多腾讯海量技术文章,请关注云加社区:https://cloud.tencent.com/developer

作者:衡阵

最近基于golang 实现一个通用的http的协议代理,把来自http的请求转换成内部的通信协议。内部协议是基于pb的,所以关键就是实现pb和http请求中的参数的转换。

研究protoc生成的go源码发现,生成的go的结构体中已经自带的json的tag,可以很方便的在json和pb之间互转。

于是想到,可以以一个请求参数来传json来实现。

var data=

var url="http://test.xx.com/cgi-bin/request?data="+urlencode(data)

http.get(url)

这样在服务端先拿到data的数据,直接用json库就可以转成相关的结构体。

这样实现虽然简单,但并不直观。对用户来说,更习惯用。

var url="http://test.xx.com/cgi-bin/request?name=hello"

这种形式来请求。由于其他语言习惯把请求参数存在一个map中,于是想golang是不是也可以这样处理。于是问题变成一个map[string]string和json的转换的故事。搜下网上发现有人提出类似的问题,还是playgroud上的一个练习。代码如下:

这个代码实现了简单的map到struct的转换,但要求类型强一致。所以需要实现弱类型的转换。后来发现,github上已经有一个开源的实现。

https://github.com/mitchellh/mapstructure 通过很简单的代码就可以实现我们想要的功能

到了这里,大部分场景都可以实现了。但有些请求是有消息嵌套的,虽然mapstructure是支持嵌套转换的,但我们的请求参数只是一层的map[string]string。

这种情况mapstructure无能为力了。看下mapstructure的源码,逻辑比较简单,既然你不支持,就改到你支持。我们定义如果有结构体嵌套,二级参数要是一个json字符串。在处理结构提的地方,如果发现传入的是个字符串,就尝试用json去处理一下,然后再走后面的逻辑。

在slice的地方也同样处理

这样处理完了之后试了一下,果然处理嵌套的结构体了。但是在实际使用的时候发现,有人竟然在pb中定义普通的字符串为bytes,这样在生成的go代码中就是[]byte类型。这种情况很不巧也会走到decodeSlice的逻辑,而我们并没有考虑兼容。事实上mapstructure这个框架就没有考虑这种情形。按json定义的标准,[]byte类型要以base64编码,我们也遵循这种规范。于是加上这个代码:

至此,这个转换基本完美。但是发现一使用,发现还是有坑存在,对应proto文件中定义的带下划线的字段,生成的struct成员代码是驼峰型的。标准库中的json可以通过反射拿到tag中的原始名称正常的输出。但我们用mapstructure默认是以字段名来解析的。

本来以为要自己处理一下,在修改一下mapstructure的源码,然而阅读代码的时候发现,mapstructure支持指定要处理的tag。并且tag处理逻辑是兼容pb生成的json tag的。我们只要在解析时指定一下tag即可。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171229A0GSQ700?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券