目前在用 gin+gorm 写一个小玩意,遇到这样的情况:
为了代码复用及写起来方便,基本都是用的 orm select *
有时候面向前台的接口不方便展示数据集中的某个字段,但是面向后端的又需要
这应该是前后端分离都会遇到的吧,请教各位大佬,比较好的解决方案是什么?
大家误会了,这是我业余写的小玩意
还在写的过程中,没有将查询到的所有数据直接返回给前端
提问是为了找一个更好的解决方案。
1
hq 2020-05-17 12:46:31 +08:00 via Android
Graphql,https://graphql.org/code/#go
|
2
heimeil 2020-05-17 12:53:55 +08:00
type User struct {
Name string `json:"name"` Password string `json:"-"` } |
5
kasper4649 2020-05-17 13:16:16 +08:00 via Android
DTO ?
|
6
pubby 2020-05-17 13:26:42 +08:00 via Android 2
var u User =.....
//举例:隐藏 User 里的 password var out = struct{ User Hide1 bool `json:"password,omitempty"` }{ User: u, } json.Marshal(out) //原理:利用 omitempty 属性的空值同名字段覆盖 |
7
CEBBCAT 2020-05-17 13:48:38 +08:00 via Android
这个 Google 一下就有了吧。可以重新定义结构体的 JSON 相关方法
|
8
qiayue 2020-05-17 15:41:24 +08:00
后端处理后再返回,每一个字段都要处理,确保返回的数字是数字,字符是字符。
另外很多时候还会返回对象,举例帖子详情接口,返回的 author 就需要是一个对象,方便展示昵称和头像 { "id": 123, "title": "帖子标题", "author":{ "id": 456, "name": "帖子作者昵称", "avatar": "帖子作者头像 URL" } } |
11
JackyCDK 2020-05-17 18:22:15 +08:00
json: - , binding: password,required
|
12
renmu 2020-05-17 18:25:34 +08:00 via Android
都是 select * 会被骂的吧😂😂性能有问题
|
13
securityCoding 2020-05-17 19:55:33 +08:00
@renmu 表设计好,索引用好并不会有什么问题...
|
14
GM 2020-05-17 23:03:40 +08:00
很简单,换 PHP 就好了!(* ̄ rǒ ̄)
|
15
winrar 2020-05-18 01:21:44 +08:00
这个 ORM 都有的吧,比如 django 的 values(fields, *expressions)
|
17
ppphp 2020-05-18 02:04:26 +08:00
我的实践上还是返回的 model 和数据表的 model 会转一下,方便点,改表也没有心理压力
|
18
baobao1270 2020-05-18 05:04:11 +08:00
.NET 有 DTO,其他语言应该也有类似的,思路就是用中间类转换一下
|
19
k9982874 2020-05-18 07:31:14 +08:00 via iPhone
先不说 select *的问题,你是把数据直接怼进 map 里?
|
20
Counter 2020-05-18 07:35:14 +08:00 via Android
创建一个专门用于输出数据的类,不要直接输出实体
|
21
wfhtqp 2020-05-18 08:41:51 +08:00
使用 tag+reflect,根据请求 fields 返回需要的字段
|
22
Wenco OP @renmu 很多种情况下都会出现操作的数据对象是一样的,就是需要的字段不同,不 select * 每个地方都要写一次,代码复用超级低。其实 OOP 思想也会有类似的问题,看怎么取舍了。
|
23
Wenco OP @JackyCDK 前台要求不展示 password,但是后台需要 password 怎么搞?写两个不同的 struct 然后转换?
|
24
Wenco OP @k9982874 https://gorm.io/docs/query.html 不需要用 map 啊,创建好表 struct 就行了
|
25
useben 2020-05-18 09:06:10 +08:00
dto vo po
|
26
reus 2020-05-18 09:06:25 +08:00
如果出什么 bug,密码泄露到前台,你就知错了。
好的设计,就算出现 bug,也不至于出现敏感数据泄露。 安全距离是很重要的,你这种做法,不安全。 |
29
dandycheung 2020-05-18 09:10:21 +08:00 via iPhone
一楼正解。
|
30
siteshen 2020-05-18 09:45:34 +08:00
// models/user.go
struct User { username string password stirng age int ... } // responses/user.go struct UserResponse { username string age int ... } func NewUserResponse(user *User) { ... } // handlers/user.go funct ReadUserHandler(req, res) { user = models.ReadUserById(req.UserId) return response.NewUserResponse(user) } |
31
siteshen 2020-05-18 09:49:37 +08:00
@siteshen 简单的说,就是你们少了一层抽象:API response 。加上之后 API 返回字段就只和 API response 层相关,不需要和 model 、logic 层耦合(甚至 model 用 ORM 实现、甚至存储换成 redis/mongodb 也不会影响前端)。
|
32
wfhtqp 2020-05-18 09:57:06 +08:00
|
33
Wenco OP @siteshen 是不是可以理解为 response 就是定义数据返回格式的,有几处不同的返回格式就定义几个 response,NewRespons 没有实际输出,只是进行数据重组?
|
34
odirus 2020-05-18 10:10:34 +08:00
举个例子,假设需要分别返回“课程信息”给 PC 端和 APP 端,他们需要返回的字段详细程度是不一样的,可以这样做
查询课程 ID -> 查询出该课程的详细信息 -> 缓存到某个地方(例如 ES ) -> 通过 Graphql 分别取各个端需要的字段信息 -> 返回给端 更新课程 ID -> 更新 DB 中的课程信息 -> 更新 ES 中的课程信息 |
35
Pythondr 2020-05-18 10:13:08 +08:00
不建议将数据库的 model 直接返回, 一般会定义一个 controller 层的 model, 这样的数据字段更具有灵活性,也更安全
|
37
ViggoSite 2020-05-18 10:22:52 +08:00
指定 Select 字段,它不香麽?
|
38
ZSeptember 2020-05-18 10:24:35 +08:00
VO,DTO,各种结构职责分离
|
39
misaka19000 2020-05-18 10:25:58 +08:00
添加 exclude 或者 include 选项
|
40
pena 2020-05-18 15:05:35 +08:00
https://github.com/pengwenwu/gin-items
不介意的话可以看下我自己写的小项目,基于 gin 的 restfull 风格的商品服务。 不定字段可以通过 scan 转到 map 里,不过性能会有影响 |
41
siteshen 2020-05-18 16:29:09 +08:00
@Wenco NewUserResponse 是其他语言中的构造函数,这样对生成的 UserResponse 可控(甚至 UserResponse 可以设计为 private 的 userResponse )。
UserResponse 也是可以复用的,下面这个例子就会复用 BasicUser 。 用户列表可能就只需要 BasicUser (用户名、头像), 查看用户详情时可能需要 UserDetail (BasicUser + 粉丝数、文章数), 查看自己的详情时可能需要 Me ( UserDetail + 收入 + 草稿箱中的文章数)。 struct BasicUser { username string avatar url } // API readUser struct UserDetail { UserResponse bio string location string n_follower int n_following int n_posts int } // 用户查看自己信息的时 struct Me { UserDetail n_fav_posts int total_cost double total_income double n_draft_posts int } // API listUser struct UserList { users BasicUser[] } |
42
asAnotherJack 2020-05-19 11:37:03 +08:00 2
https://colobu.com/2017/06/21/json-tricks-in-Go/
刚好前段时间忘了在哪收藏的一篇文章,有楼主需要的 |
43
Wenco OP @asAnotherJack 感谢,很有用!
|