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