Подтвердить что ты не робот

Периодически промывающий канал в голанге

Мне нужно периодически очищать содержимое канала. Я сделал это с len(), и мне интересно, есть ли лучший способ сделать это.

http://play.golang.org/p/YzaI_2c_-F

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    commch := make(chan int, 100)
    go fillchan(commch)
    drainchan(commch)
}

func fillchan(commch chan int) {
    for {
        select {
        case <-time.Tick(30 * time.Millisecond):
            commch <- rand.Int()
        }
    }
}

func drainchan(commch chan int) {
    for {
        chanlen := len(commch) // get number of entries in channel
        time.Sleep(1 * time.Second)
        for i := 0; i <= chanlen; i++ { //flush them based on chanlen
            fmt.Printf("chan len: %s num: %s\n", chanlen, <-commch)
        }
    }
}

EDIT 1: кажется, что это лучший способ сделать это http://play.golang.org/p/4Kp8VwO4yl

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    commch := make(chan int, 1000)
    go fillchan(commch)
    for {
        select {
        case <-time.Tick(1000 * time.Millisecond):
            drainchan(commch)
        }
    }
}

func fillchan(commch chan int) {
    for {
        select {
        case <-time.Tick(300 * time.Millisecond):
            commch <- rand.Int()
        }
    }
}

func drainchan(commch chan int) {
    for {
        select {
        case e := <-commch:
            fmt.Printf("%s\n",e)
        default:
            return
        }
    }
}

ИЗМЕНИТЬ 2: удалить выбранный, предотвратить утечку памяти со временем. http://play.golang.org/p/WybAhRE3u4

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    commch := make(chan int, 1000)
    go fillchan(commch)
    for _ = range time.Tick(1000 * time.Millisecond) {
        drainchan(commch)
    }
}

func fillchan(commch chan int) {
    for _ = range time.Tick(300 * time.Millisecond) {
        commch <- rand.Int()
    }
}

func drainchan(commch chan int) {
    for {
        select {
        case e := <-commch:
            fmt.Printf("%s\n", e)
        default:
            return
        }
    }
}
4b9b3361

Ответ 1

Необходимость сбросить содержимое канала будет необычной. Каналы не предоставляют эту функцию, но вы можете сделать goroutine, который будет вести себя таким образом (... если вы действительно этого захотите).

Как правило, вы будете больше думать о goroutine, который вводит один канал и выводит на другой; оба канала имеют один и тот же тип данных. Вы могли бы в принципе моделировать все буферизованные каналы таким образом; для своих клиентов, горутин ведет себя как обычный буферный канал, потому что он передает то, что получает.

Добавьте третий канал в goroutine, в сочетании с выбором между ним и входом. Это позволит вам запускать опорожнение буфера без каких-либо условий гонки. Простой.

Теперь к goroutine подключены три канала - два входа и выход. Поэтому, когда вы разрабатываете вещи, которые будут использовать его, вы можете рассуждать о семантике промывки этих данных.

Относительные пружины. Рассмотрим goroutine с одним входом и одним выходным каналом. Он обеспечивает буфер перезаписи фиксированного размера, то есть тот, который всегда готов к чтению с его входного канала, даже когда выходной канал заблокирован. Для этого также потребуется выбор со стандартным случаем, но третий канал не нужен. Перезаписывающие буферы имеют ясный прецедент: когда каналы и goroutines подключены к циклам, тупик может быть весьма вероятным. Перезаписывающие буферы пригождаются как одно из возможных решений для взаимоблокировок, потому что некоторые данные бесполезны, когда они опаздывают - например, вы могли бы, например, выбросить события мыши в графический интерфейс, когда приложение слишком занято, чтобы ответить на них.