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