Периодически промывающий канал в голанге
Мне нужно периодически очищать содержимое канала.
Я сделал это с 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
}
}
}
Ответы
Ответ 1
Необходимость сбросить содержимое канала будет необычной. Каналы не предоставляют эту функцию, но вы можете сделать goroutine, который будет вести себя таким образом (... если вы действительно этого захотите).
Как правило, вы будете больше думать о goroutine, который вводит один канал и выводит на другой; оба канала имеют один и тот же тип данных. Вы могли бы в принципе моделировать все буферизованные каналы таким образом; для своих клиентов, горутин ведет себя как обычный буферный канал, потому что он передает то, что получает.
Добавьте третий канал в goroutine, в сочетании с выбором между ним и входом. Это позволит вам запускать опорожнение буфера без каких-либо условий гонки. Простой.
Теперь к goroutine подключены три канала - два входа и выход. Поэтому, когда вы разрабатываете вещи, которые будут использовать его, вы можете рассуждать о семантике промывки этих данных.
Относительные пружины. Рассмотрим goroutine с одним входом и одним выходным каналом. Он обеспечивает буфер перезаписи фиксированного размера, то есть тот, который всегда готов к чтению с его входного канала, даже когда выходной канал заблокирован. Для этого также потребуется выбор со стандартным случаем, но третий канал не нужен. Перезаписывающие буферы имеют ясный прецедент: когда каналы и goroutines подключены к циклам, тупик может быть весьма вероятным. Перезаписывающие буферы пригождаются как одно из возможных решений для взаимоблокировок, потому что некоторые данные бесполезны, когда они опаздывают - например, вы могли бы, например, выбросить события мыши в графический интерфейс, когда приложение слишком занято, чтобы ответить на них.
Ответ 2
BatchingChannel
from https://github.com/eapache/channels делает то, что вам нужно, я думаю.