简体   繁体   中英

How to read channel without waiting setting in another goroutine?

I have a problem with channel using in goroutine.

var test = make(chan string)

func main() {
    go initChan()

    for i := 0; i < 2; i++ {
        go readChan()
    }

    var input string
    fmt.Scanln(&input)
}

func initChan() {
    for i := 0; i < 100; i++ {
        test <- "Iteration num: " + strconv.Itoa(i)
        time.Sleep(time.Second * 5)
    }
}

func readChan() {
    for {
        message := <- test
        log.Println(message)
    }
}

output:

2019/12/24 08:21:17 Iteration num: 0
2019/12/24 08:21:22 Iteration num: 1
2019/12/24 08:21:27 Iteration num: 2
2019/12/24 08:21:32 Iteration num: 3
2019/12/24 08:21:37 Iteration num: 4
2019/12/24 08:21:42 Iteration num: 5
................................

I need threads reading without waiting for update of test var. Now every readChan() is waiting for initChan() to update test var.

Is it to possible to make readChan() threads work in one time without waiting initChan() for every thread?

A demon is created which push all the messages from test channel to all other listening routines.

var test = make(chan string)

var mapChan = make(map[int]chan string)
var count = 3

func main() {
    go initChan()
    go deamon()
    for i := 0; i < count; i++ {
        mapChan[i] = make(chan string)
        go readChan(i)
    }

    var input string
    fmt.Scanln(&input)
}

func deamon() {
    for {
        message := <-test
        for i := 0; i < count; i++ {
            mapChan[i] <- message
        }
    }
}

func initChan() {
    for i := 0; i < 100; i++ {
        test <- "Iteration num: " + strconv.Itoa(i)
        time.Sleep(time.Second * 1)
    }
}

func readChan(i int) {
    for {
        select {

        case message := <-mapChan[i]:
            log.Println(message)
        default:
            // Do for not when written on channel
        }
    }
}

If I correctly understand your question, this solution might help. I used one buffered channel of size 1 so that goroutine which is the sender is never blocked which is in the case of unbuffered channels. You can read more about channels: Behaviour of channles

package main

import (
    "log"
    "strconv"
    "sync"
    "time"
)

// Buffered channel with size 1 guarantees delayed delivery of data
// As soon as the goroutine sends to the channel, the reciever goroutine dequeus it
// Then the reciver goroutines does the work, but the sender goroutine isn't blocked
// As the size is again 0 after the reciever recieved it but might haven't processed it yet
var test = make(chan string, 1)

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    // Waits for other goroutines to complete before the main goroutine returns
    defer wg.Wait()
    go initChan(&wg)
    go readChan(&wg)
}

func initChan(wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 100; i++ {
        // Sends continuously
        test <- "Iteration num: " + strconv.Itoa(i)
        time.Sleep(time.Second * 5)
    }
    close(test)
}

func readChan(wg *sync.WaitGroup) {
    defer wg.Done()
    var message string
    var ok bool
    // Reciever deques the value as soon as it recieves it
    // But might take time to proceed
    for {
        select {
        case message, ok = <-test:
            // If channel is closed
            if ok == false {
                return
            }
            log.Println(message)
        default:
            log.Println(message)
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM