Come sapere che un canale bufferizzato è pieno? Non so di essere bloccato quando il canale bufferizzato è pieno, invece ho scelto di rilasciare l'elemento inviato al canale bufferizzato.Golang - Come sapere che un canale bufferizzato è pieno
risposta
È possibile utilizzare select
statement con un valore predefinito. Nel caso in cui non è possibile fare qualsiasi dei casi, come l'invio di un canale pieno, la dichiarazione farà il default:
package main
import "fmt"
func main() {
ch := make(chan int, 1)
// Fill it up
ch <- 1
select {
case ch <- 2: // Put 2 in the channel unless it is full
default:
fmt.Println("Channel full. Discarding value")
}
}
uscita:
canale pieno. Scartando valore
Playground:http://play.golang.org/p/1QOLbj2Kz2
controllare senza inviare
E 'anche possibile controllare il numero di elementi in coda in un canale utilizzando len(ch)
, come indicato nel Go specifications. Questo in combinazione con cap
ci consente di verificare se un canale è pieno senza inviare alcun dato.
if len(ch) == cap(ch) {
// Channel was full, but might not be by now
} else {
// Channel wasn't full, but might be by now
}
Si noti che il risultato del confronto potrebbe non essere valido nel momento in cui entra il blocco if
Ma cosa succede se si vuole solo controllare se il buffer è pieno, non si scrive su di esso anche quando non lo è? C'è un modo per farlo? – Tom
@Tom Si può effettivamente testare 'if len (ch) == cap (ch) {...}' dove 'len (ch)' è il numero di elementi nel canale e 'cap (ch)' è la capacità . Tuttavia, potrebbe non essere valido quando si inserisce il blocco if. – ANisus
fantastico - ora questa è una risposta completa! – Tom
invece ho scelto di rilasciare l'elemento inviato al canale tamponata.
che si chiama "canale traboccante", e trovi la risposta di Anisus implementato in eapache/channels/overflowing_channel.go
:
for elem := range ch.input {
// if we can't write it immediately, drop it and move on
select {
case ch.output <- elem:
default:
}
}
close(ch.output)
Ma quel progetto eapache/channels implementa altre strategie così:
OverflowingChannel
implementa ilChannel
interfaccia in un modo che non blocca mai lo scrittore.
In particolare, se un valore è scritto su unOverflowingChannel
quando il suo buffer è pieno
(o, in un caso non bufferizzato, quando il destinatario non è pronto), quel valore viene semplicemente scartato.
Per il comportamento opposto (scartando l'elemento più vecchio, non l'ultima) vedere
RingChannel
.
Una buona risposta. Canali traboccanti che perdono il più vecchio o il più nuovo oggetto possono a volte essere strumenti vitali nella vostra cassetta degli attrezzi. Considera un anello di goroutine: normalmente, qualsiasi loop (a.k.a * cycle *) causa un rischio di stallo. La modifica di uno dei canali per essere traboccante risolve questo problema. Perdere alcuni eventi non importa se sono il tipo che può diventare stantio può essere facilmente sostituito. Ci sono (ovviamente) altri modi per risolvere lo stesso problema di deadlock. –
Un altro esempio utile che ho trovato è stato this nifty implementation di Ring Buffer.
La citazione dalla fonte:
L'idea è semplice: collegare due canali bufferizzati i goroutine che inoltra i messaggi dal canale in ingresso al canale uscente . Ogni volta che non è possibile collocare un nuovo messaggio sul canale in uscita , estrarre un messaggio dal canale in uscita (che il è il messaggio più vecchio nel buffer), rilasciarlo e posizionare il nuovo messaggio nella nuova versione in uscita. canale.
Partenza this C version così ...
Usa len(channel)
per verificare quanti elementi sono attualmente nel canale e che, per confrontare cap(channel)
, la sua capacità:
func TestChannelFull(t *testing.T) {
chansize := 100
ch := make(chan bool, chansize)
t.Log(cap(ch))
t.Log(len(ch))
for len(ch) < cap(ch) {
ch <- true
}
t.Log(len(ch))
t.Log("quit because channel is full")
}
init_test.go:25: 100
init_test.go:26: 0
init_test.go:30: 100
init_test.go:31: quit because channel is full
PASS
- 1. Il canale bufferizzato di Go è lockless?
- 2. elenca tutti gli elementi in un canale bufferizzato
- 3. Come sapere se un canale SSH paramiko è disconnesso?
- 4. Golang handlefunc con il canale
- 5. È possibile utilizzare il canale bufferizzato di Go come coda thread-safe?
- 6. IO bufferizzato vs non bufferizzato
- 7. JavaScript: Sapere quando un'immagine è a pieno carico
- 8. Golang - Qual è la dimensione del buffer del canale?
- 9. E 'possibile associare un canale golang in un modello
- 10. Lettura del numero specifico di byte da un lettore bufferizzato in golang
- 11. Come sapere che l'attività è stata completata?
- 12. Come disegnare un poligono pieno?
- 13. Determinare quanto è pieno un cluster Cassandra
- 14. FileResult bufferizzato in memoria
- 15. Perché il mio canale Golang scrive blocco per sempre?
- 16. Fai crescere EditText così come è pieno
- 17. C'è un campo per sapere se il canale youtube è verificato dall'API Youtube?
- 18. incendi Window.loaded prima che la finestra è a pieno carico
- 19. TF30042: il database è pieno
- 20. Come si chiude un canale che inviano più goroutine?
- 21. Come posso sapere se un'altra app ha registrato un canale Remoto IPC?
- 22. Come si simula un dispositivo periferico bufferizzato con SwingWorker?
- 23. Come sapere se un elemento è reso?
- 24. Come disegnare un cerchio pieno in Java?
- 25. Come sapere se una variabile di tipo arbitrario è zero in Golang?
- 26. Come sapere che l'elemento di trascinamento è su quale elemento?
- 27. Cosa succede quando localStorage è pieno?
- 28. Il buffer SocketAsyncEventArgs è pieno di zeri
- 29. Come faccio a sapere che il columnizing è fatto?
- 30. Canale di sola lettura Canale
La premessa della questione è che vuoi evitare che il canale si riempia mai. Ma il fatto che i canali * possano * sincronizzarsi e quindi bloccare entrambe le estremità è una parte importante del pensiero di CSP. Non tentare troppo di impedire che i buffer si riempiano fino a quando non si capisce la sincronizzazione in modo più completo. Come esercizio, prova a risolvere diversi problemi usando solo i canali * unbuffered *. Quindi puoi vedere come aggiungere il buffering in seguito può essere un miglioramento delle prestazioni di un sistema già funzionante. (Di tanto in tanto casi in cui troppo buffer può persino ridurre le prestazioni.) –