V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
awanganddong
V2EX  ›  Go 编程语言

go 协程请求数据

  •  
  •   awanganddong · 2023-01-15 09:58:31 +08:00 · 1630 次点击
    这是一个创建于 471 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我一个接口里边,需要多次操作数据库,现在想通过协程来实现。 下边这个 demo 是一个样例, 我在 resp 怎么区分协程的返回值,这里边还有些不太清晰。

    func main() {
        var ch = make(chan []byte)
        go request("https://www.baidu.com", ch)
        go request("https://www.taobao.com", ch)
        go request("https://www.google.com", ch)
    
        i := 0
        timer := time.NewTimer(time.Second * 3)
    L:
        for {
            select {
            case <-timer.C:
                break L
            case resp := <-ch:
                fmt.Printf("%d\n", len(resp))
                // 接收 3 个之后关闭 chan
                i++
                if i == 3 {
                    close(ch)
                    break L
                }
            }
        }
        // more code...
    }
    
    7 条回复    2023-01-16 15:48:16 +08:00
    catVSdog
        1
    catVSdog  
       2023-01-15 10:22:20 +08:00
    你是要区分每个协程的返回值吗?不同的协程对应不同处理方式?

    那么再构建一个一个结构体,例如:

    type CRes struct {

    }
    catVSdog
        2
    catVSdog  
       2023-01-15 10:28:01 +08:00   ❤️ 2
    你是要区分每个协程的返回值吗?不同的协程(或者说:不同的数据库)对应不同处理方式?

    那么再构建一个一个结构体,例如:


    type CRes struct {
    ChannelType int // taobao:1, baidu:2, google:3
    Res interfact{}
    }



    ch := make(chan CRes)

    每个协程函数返回 CRes ,然后将 CRes 返回到 channel 中。在接受、处理 channel 的函数中,根据不同的 channelType 进行处理
    awanganddong
        3
    awanganddong  
    OP
       2023-01-15 11:34:48 +08:00
    明白了,谢谢你。
    awanganddong
        4
    awanganddong  
    OP
       2023-01-15 16:41:17 +08:00
    我修改后的 demo 发下

    package main

    import (
    "fmt"
    "time"
    )

    type CRes struct {
    ChannelType int
    Res interface{}
    }

    func main() {
    var ch = make(chan CRes)
    go test1(ch)
    go test2(ch)
    for i := 0; i < 2; i++ {
    select {
    case <-time.After(time.Second * 5):
    fmt.Println("超时操作")
    break
    case resp := <-ch:
    if resp.ChannelType == 1 {
    fmt.Printf("这是 1 的数据")
    }
    if resp.ChannelType == 2 {
    fmt.Printf("这是 2 的数据")
    }
    break
    default:
    fmt.Println("资源已满,请稍后再试")
    }
    }
    }
    func test1(ch chan CRes) {
    res := CRes{
    ChannelType: 1,
    Res: nil,
    }
    ch <- res
    }

    func test2(ch chan CRes) {
    res := CRes{
    ChannelType: 2,
    Res: nil,
    }
    ch <- res
    }
    jorneyr
        5
    jorneyr  
       2023-01-15 20:14:16 +08:00
    md5(url) 作为任务的 ID ,返回的时候也对应的带上这个 ID 。
    morty0
        6
    morty0  
       2023-01-16 09:57:56 +08:00
    context 带个 id 进去
    ryalu
        7
    ryalu  
       2023-01-16 15:48:16 +08:00
    没必要这么复杂吧,直接用 errgroup 。最近有个协程的库看起来还可以 https://github.com/sourcegraph/conc
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   795 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 21:28 · PVG 05:28 · LAX 14:28 · JFK 17:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.