go开发中过度使用mapinterface{}?
来源:stackoverflow
时间:2024-04-30 14:21:39 208浏览 收藏
在Golang实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《go开发中过度使用mapinterface{}?》,聊聊,希望可以帮助到正在努力赚钱的你。
我的大部分开发经验来自 php 和 javascript 等动态类型语言。通过在 golang 中重新创建一些旧的 php/javascript rest api,我已经练习 golang 大约一个月了。我觉得大多数时候我并没有以 golang 的方式做事。或者更一般地说,我不习惯使用强类型语言。我觉得我过度使用了 map[string]interface{}
及其片段来包装来自 http 请求的数据或作为 json http 输出发出的数据。那么我想知道的是,我要描述的内容是否违背了golang的开发理念?或者如果我违反了强类型语言的开发原则?
目前,我用 golang 重写的 rest api 程序流程大约 90% 都可以通过这 5 个步骤来描述。
第 1 步 - 接收数据
我从 http.request.parseform()
接收 http 表单数据,格式为 formvals := map[string][]string
。有时我会存储需要解组的序列化 json 对象,例如 jsonuserinfo := json.unmarshal(formvals["user_information"][0]) /* 给出一些复杂的 json 对象 */
。
第 2 步 - 验证数据
我对 formvals
进行验证,以确保在 sql 查询中使用它之前所有数据值都是我所期望的。我将所有内容视为字符串,然后使用 regex 来确定字符串格式和业务逻辑是否有效(例如 isemail、isnumeric、isfloat、iscaslcompliant、iseligibleforvoting、islibrarycardexpired 等)。我已经为这些类型的验证编写了自己的正则表达式和自定义函数
第 3 步 - 将数据绑定到 sql 查询
我使用golang的database/sql.db
来获取我的formvals并将它们绑定到我的查询和执行函数,例如query("select * from tbluser where user_id = ?, user_birthday > ? ",formvals["user_id"][ 0], jsonuserinfo["生日"])
.我从不关心我作为要绑定的参数提供的数据类型,因此它们可能都是字符串。我相信上面步骤中的验证已确定它们可以用于 sql。
第 4 步 - 将 sql 结果绑定到 []map[string]interface{}{}
我 scan()
将查询结果写入 sqlresult := []map[string]interface{}{}
因为我不关心值类型是否为 null、字符串、浮点数、整数或其他类型。因此 sqlresult
的架构可能如下所示:
sqlresult => [0] { "user_id":"1" "user_name":"bob smith" "age":"45" "weight":"34.22" }, [1] { "user_id":"2" "user_name":"jane do" "age":nil "weight":"22.22" }
我编写了自己的急切加载函数,以便可以绑定更多信息,例如 eagerload("tbladdress", "join on tbladdress.user_id",&sqlresult)
,然后使用 []map 类型的更多信息填充
,如下所示:sqlresult
[string]interface{}{}
sqlResult => [0] { "user_id":"1" "user_name":"Bob Smith" "age":"45" "weight":"34.22" "addresses"=> [0] { "type":"home" "address1":"56 Front Street West" "postal":"L3L3L3" "lat":"34.3422242" "lng":"34.5523422" } [1] { "type":"work" "address1":"5 Kennedy Avenue" "postal":"L3L3L3" "lat":"34.3422242" "lng":"34.5523422" } }, [1] { "user_id":"2" "user_name":"Jane Do" "age":nil "weight":"22.22" "addresses"=> [0] { "type":"home" "address1":"56 Front Street West" "postal":"L3L3L3" "lat":"34.3422242" "lng":"34.5523422" } }
第 5 步 - json 编组并发送 http 响应
然后我执行 http.responsewriter.write(json.marshal(sqlresult))
并为我的 rest api 输出数据
最近,我一直在重新审视带有代码示例的文章,这些代码示例在我本来会使用 map[string]interface{}
的地方使用结构。例如,我想使用其他 golang 开发人员会使用的更标准的方法来重构步骤 2。所以我找到了这个https://godoc.org/gopkg.in/go-演示/validator.v9,除了它的所有示例都是结构体。我还注意到,大多数谈论 database/sql
的博客都会将其 sql 结果扫描到类型化变量或具有类型化属性的结构中,而不是我的步骤 4,后者只是将所有内容放入 map[string]interface{}
因此,我开始写这个问题。我觉得 map[string] 接口{}
非常有用,因为大多数时候,我并不真正关心数据是什么,它让我可以在步骤 4 中自由地在我之前构建任何数据模式。将其转储为 json http 响应。我用尽可能少的代码来完成这一切。但这意味着我的代码还没有准备好利用 go 的验证工具,而且它似乎不符合 golang 社区的做事方式。
所以我的问题是,其他 golang 开发人员对步骤 2 和步骤 4 做了什么?特别是在第 4 步中……golang 开发人员真的鼓励通过结构和强类型属性指定数据模式吗?他们是否还指定具有强类型属性的结构以及他们进行的每个急切加载调用?这看起来是不是代码冗长了很多?
解决方案
这实际上取决于需求,就像您所说的那样,您不需要处理来自请求或 sql 结果的 json 。然后您可以轻松解组到 interface{}
。并编组来自 sql 结果的 json。
对于第 2 步
golang 有一个库,用于验证结构体,用于使用内部字段的标签来解组 json。
https://github.com/go-playground/validator
type test struct { field `validate:"max=10,min=1"` } // max will be checked then min
你也可以去godoc获取validation library。这是使用struct标签验证json值的非常好的实现。
对于第 4 步
大多数时候,如果我们知道 json 的格式和数据,我们就会使用结构。因为它为我们提供了对数据类型和其他功能的更多控制。例如,如果您想要清空 json 字段,而您的 json 中不需要它。您应该将 struct 与 _
json 标记一起使用。
现在你已经说过你不关心来自sql的结果是否为空。但如果你再次这样做,就会涉及到使用 struct。您可以使用 sql.NullTypes
将结果扫描到结构中。如果您想在发送响应时 marshaling
数据时省略 json 对象,也可以为 omitempty
提供 json 标记。
结构体值编码为 json 对象。每个导出的结构体字段 成为对象的成员,使用字段名作为对象 键,除非由于下面给出的原因之一而省略该字段。
每个结构体字段的编码可以通过格式自定义 存储在结构字段标记中“json”键下的字符串。这 格式字符串给出字段的名称,后面可能跟着一个 以逗号分隔的选项列表。该名称可以为空,以便 指定选项而不覆盖默认字段名称。
“omitempty”选项指定应从 如果字段有空值,则编码,定义为 false、0、a nil 指针、nil 接口值以及任何空数组、切片、映射、 或字符串。
作为特殊情况,如果字段标记为“-”,则该字段始终为 省略。请注意,仍然可以使用以下命令生成名称为“-”的字段 标签“-,”。
json 标签示例
// Field appears in JSON as key "myName". Field int `json:"myName"` // Field appears in JSON as key "myName" and // the field is omitted from the object if its value is empty, // as defined above. Field int `json:"myName,omitempty"` // Field appears in JSON as key "Field" (the default), but // the field is skipped if empty. // Note the leading comma. Field int `json:",omitempty"` // Field is ignored by this package. Field int `json:"-"` // Field appears in JSON as key "-". Field int `json:"-,"`
您可以从 golang 规范 json marshal 中给出的上述信息进行分析。struct 对 json 提供了如此多的控制。这就是 golang 开发人员最有可能使用结构的原因。
现在,在使用 map[string]interface{}
时,当您不知道来自服务器的 json 结构或字段类型时,应该使用它。大多数 golang 开发人员都会尽可能坚持使用结构。
文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《go开发中过度使用mapinterface{}?》文章吧,也可关注golang学习网公众号了解相关技术文章。
-
502 收藏
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
139 收藏
-
204 收藏
-
325 收藏
-
477 收藏
-
486 收藏
-
439 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习