
需求:
fun main(){ x1(id string) (objectEntity entity, error) {} x2(id string) (objectEntity []entity, error) {} x3(id string) (objectEntity entity, error) {} } x1(),x2(),x3()分别是三个互相不关联的 3 个 sql 查询. x1 会返回一个 objectEntity, error, x2 会返回一个[]objectEntity, x3 会返回一个 objectEntity. 我会拿到这 3 个返回值,然后进行拼接.
本来直接使用 goroutine 和 channel 来进行请求. 但是我遇到一个问题, 不管是 x1,x2,x3 进行查询,返回值 都有 error. 大家有什么好的办法吗?
1 Immortal 2020 年 7 月 23 日 "不管是 x1,x2,x3 进行查询,返回值 都有 error" ??? 有 error 不就是报错了么,不能先处理了 error 再考虑后面拼接的问题么 具体得看你们容错程度,一个或多个出错了就不参与拼接 还是 不能有 error 必须保证全部有结果才能拼接 再另外说一句,既然要同步拼接,根本不需要走协程,同步执行就行了.异步反而更麻烦 |
2 caryqy 2020 年 7 月 23 日 这个好像和协程没啥关系,要根据你需求来决定吧,比如某个返回值有 error 时用个默认值来代替 |
3 Vegetable 2020 年 7 月 23 日 再定义一个 channel 处理 error 呗 |
4 KaynW 2020 年 7 月 23 日 搞不懂这为什么是协程的问题 |
5 xmge 2020 年 7 月 23 日 至少写个能跑起来的伪代码,让大家跑一下吧...... 要不大家都不知道你的代码是咋样的,也无法给你解决问题 |
6 wangritian 2020 年 7 月 23 日 xResult { obj objectEntity err Error } 不过我觉得这法子不太标准 |
7 Zach369 OP @Immortal 第一: 异步还是有必要的, 假如 x1 需要 0.5s x2 需要 0.5s x3 需要 0.8s. 如果同步执行,就需要 1.8s. 异步查询,0.8s 就可以拿到所有的结果. 第二: 查询有错误,是因为所有的 orm 包在查询的时候,都会返回 error 这个值. 我目前抽出来的函数 都没有直接对 error 进行处理.都是返回正常的结果和 error.然后在外层统一处理. |
8 vvmint233 2020 年 7 月 23 日 把[]objectEntity 和 error 合成为一个结构体 ```golang type A struct { list []objectEntity err error } ``` 然后错误逻辑放到 service 层做处理 |
9 bruce0 2020 年 7 月 23 日 不管有没有协程,不都是应该先处理 error? 只要 error 不是 nil 直接返回给调用者处理就行了 |
10 Zach369 OP @all 我加了伪代码 求 ``` 我加了伪代码... 求大家帮忙写个 gorouter ``` func main() { id := 1 user1, err := x1(id) if err != nil { // 处理 } userList, err := x2(id) if err != nil { // 处理 } user2, err := x3(id) if err != nil { // 处理 } // 然后 user1, userList, user2 进行拼接 } type User struct { Id int `json:"id"` Name string `json:"name"` } func x1(id int) (User, error) { var err error user := User{ Id: 1, Name: "xx", } return user, err } func x2(id int) ([]User, error) { var err error user := User{ Id: 1, Name: "xx", } userList := []User{user, user} return userList, err } func x3(id int) (User, error) { var err error var user User { } err = errors.New("假设出现错误") return user, err } ``` ``` |
11 Immortal 2020 年 7 月 23 日 @Zach369 #7 我不知道你用的什么 orm 包,常用的 gorm 查询结果是不可能有 error 的,除非是查询结果不存在会有个"record not found"的 error 异步这个你说的是对的,如果所有查询都正常的话. 粗略想了下你要用 channel 需要就需要把结果和 error 统一包一个结构体.可能用 sync.WaitGroup 更简单一些. |
12 Zach369 OP ``` func main() { id := 1 user1, err := x1(id) if err != nil { // 处理 } userList, err := x2(id) if err != nil { // 处理 } user2, err := x3(id) if err != nil { // 处理 } // 然后 user1, userList, user2 进行拼接 } type User struct { Id int `json:"id"` Name string `json:"name"` } func x1(id int) (User, error) { var err error user := User{ Id: 1, Name: "xx", } return user, err } func x2(id int) ([]User, error) { var err error user := User{ Id: 1, Name: "xx", } userList := []User{user, user} return userList, err } func x3(id int) (User, error) { var err error var user User { } err = errors.New("假设出现错误") return user, err } ``` |
13 mengzhuo 2020 年 7 月 23 日 你这用 waitgroup 最合适了 wg.Add(3) errCh := make(chan error) userCh := make(chan *User) go func(){ defer wg.Done() user, err := x1() if err != nil { } }() |
14 icexin 2020 年 7 月 23 日 用 errgroup 来做非常简单 https://gist.github.com/icexin/dda98e3c7dbbf2d8b37ef1fc79267197 |
15 Immortal 2020 年 7 月 23 日 |
16 tlday 2020 年 7 月 23 日 根本原因还是 error 是什么,对于 error 应该怎么处理,因为三个 err 的含义或者容忍度可能不一样,一起处理感觉是在偷懒。你的问题跟 goroutine 没有什么关系。 一起处理的话上面的那些 xxgroup 的例子可行,但是有点违背 go 的设计原则。因为本质上都是在“通过共享来传递消息”,通过共享几个 data 变量来在 routine 间传递消息不是 golang 推荐的做法。(我不确定现在 golang 还说不说这个设计理念了,好几年没写过 golang 了) BTW,我觉得你的数据库结构设计的可能有点问题,join 语句效率也没有低到这个程度吧,感觉你在强行拿 goroutine 做一个不必要的优化,“拿着锤子看什么都是钉子”系列。 |
17 vvmint233 2020 年 8 月 10 日 对此封了一个结构, 欢迎拍砖 https://github.com/mint-leaf/gotokit/tree/master/task |