关于 go 协程的一个问题?

2020-07-23 09:41:18 +08:00
 Zach369

需求:

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. 大家有什么好的办法吗?

2558 次点击
所在节点    Go 编程语言
17 条回复
Immortal
2020-07-23 09:45:19 +08:00
"不管是 x1,x2,x3 进行查询,返回值 都有 error" ???
有 error 不就是报错了么,不能先处理了 error 再考虑后面拼接的问题么
具体得看你们容错程度,一个或多个出错了就不参与拼接 还是 不能有 error 必须保证全部有结果才能拼接

再另外说一句,既然要同步拼接,根本不需要走协程,同步执行就行了.异步反而更麻烦
caryqy
2020-07-23 09:48:11 +08:00
这个好像和协程没啥关系,要根据你需求来决定吧,比如某个返回值有 error 时用个默认值来代替
Vegetable
2020-07-23 09:50:02 +08:00
再定义一个 channel 处理 error 呗
KaynW
2020-07-23 09:50:44 +08:00
搞不懂这为什么是协程的问题
xmge
2020-07-23 09:50:45 +08:00
至少写个能跑起来的伪代码,让大家跑一下吧...... 要不大家都不知道你的代码是咋样的,也无法给你解决问题
wangritian
2020-07-23 09:51:22 +08:00
xResult {
obj objectEntity
err Error
}
不过我觉得这法子不太标准
Zach369
2020-07-23 09:52:39 +08:00
@Immortal 第一: 异步还是有必要的, 假如 x1 需要 0.5s x2 需要 0.5s x3 需要 0.8s. 如果同步执行,就需要 1.8s. 异步查询,0.8s 就可以拿到所有的结果. 第二: 查询有错误,是因为所有的 orm 包在查询的时候,都会返回 error 这个值. 我目前抽出来的函数 都没有直接对 error 进行处理.都是返回正常的结果和 error.然后在外层统一处理.
vvmint233
2020-07-23 09:55:01 +08:00
把[]objectEntity 和 error 合成为一个结构体
```golang
type A struct {
list []objectEntity
err error
}
```
然后错误逻辑放到 service 层做处理
bruce0
2020-07-23 09:57:52 +08:00
不管有没有协程,不都是应该先处理 error?
只要 error 不是 nil
直接返回给调用者处理就行了
Zach369
2020-07-23 10:07:45 +08:00
@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
}

```

```
Immortal
2020-07-23 10:08:28 +08:00
@Zach369 #7
我不知道你用的什么 orm 包,常用的 gorm 查询结果是不可能有 error 的,除非是查询结果不存在会有个"record not found"的 error

异步这个你说的是对的,如果所有查询都正常的话.
粗略想了下你要用 channel 需要就需要把结果和 error 统一包一个结构体.可能用 sync.WaitGroup 更简单一些.
Zach369
2020-07-23 10:08:57 +08:00
```
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
}

```
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 {

}
}()
icexin
2020-07-23 10:32:46 +08:00
Immortal
2020-07-23 10:48:51 +08:00
tlday
2020-07-23 12:39:17 +08:00
根本原因还是 error 是什么,对于 error 应该怎么处理,因为三个 err 的含义或者容忍度可能不一样,一起处理感觉是在偷懒。你的问题跟 goroutine 没有什么关系。
一起处理的话上面的那些 xxgroup 的例子可行,但是有点违背 go 的设计原则。因为本质上都是在“通过共享来传递消息”,通过共享几个 data 变量来在 routine 间传递消息不是 golang 推荐的做法。(我不确定现在 golang 还说不说这个设计理念了,好几年没写过 golang 了)
BTW,我觉得你的数据库结构设计的可能有点问题,join 语句效率也没有低到这个程度吧,感觉你在强行拿 goroutine 做一个不必要的优化,“拿着锤子看什么都是钉子”系列。
vvmint233
2020-08-10 10:50:20 +08:00
对此封了一个结构, 欢迎拍砖 https://github.com/mint-leaf/gotokit/tree/master/task

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/692391

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX