go并发模式 tee-channel

package main

import (
    "context"
    "fmt"
    "time"
)

func teeChannel(ctx context.Context, value <-chan int) (<-chan int, <-chan int) {
    ch1 := make(chan int)
    ch2 := make(chan int)

    go func() {
        defer close(ch1)
        defer close(ch2)
        for v := range value {
            var ch1, ch2 = ch1, ch2
            for i := 0; i < 2; i++ {
                select {
                case <-ctx.Done():
                    return
                case ch1 <- v:
                    ch1 = nil //避免重复发送,置空
                case ch2 <- v:
                    ch2 = nil
                }
            }
        }
    }()

    return ch1, ch2
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    stream := make(chan int)

    ch1, ch2 := teeChannel(ctx, stream)

    go func() {
        defer close(stream)
        for i := 0; i < 5; i++ {
            stream <- i + 1
            time.Sleep(time.Millisecond * 100)
        }
    }()

    for {
        select {
        case <-ctx.Done():
            return
        case v, ok := <-ch1:
            if !ok {
                return
            }
            fmt.Printf("ch1:%d \n", v)
        case v, ok := <-ch2:
            if !ok {
                return
            }
            fmt.Printf("ch2:%d \n", v)
        }
        if ch1 == nil && ch2 == nil {
            break
        }
    }
    fmt.Println("All Done")
}

 【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/facetwitter/p/18293868

posted @ 2024-07-10 13:13  saneim  阅读(2)  评论(0编辑  收藏  举报