Is there a (non destructive) way to list all the element in a buffered channel?
The only thing I can think about is to cycle all of them, reinserting them at the end. This doesn't seem the smartest approach.
Link to playground
c := make(chan int, 100)
c <- 111
c <- 222
for i:=0;i<2;i++ {
element := <- c
fmt.Println(element)
c <- element
}
fmt.Println(len(c))
No you can't, you can write your own blocking queue based on a list if you want to do that.
This thread from 2011 offered some wrapper around a channel in order to enable a Peek() function, but that was more a workaround than anything else.
type PeekChanInt struct {
in <-chan int
out chan int
}
The general conclusion was:
A synchronous channel has no head (it's like a zero-length slice)
You can't do that because
a) it gets put back at the tail of the queue rather than the end and
b) a writer may have got there first, so the put may block.
I have wanted a feature like this in the past. It can make sense when there is only one consumer of the channel (I wanted it to peek at the first mouse event to do hit testing before deciding whether to consume it)
You can simulate it with a process acting as intermediary, but you'd have to do it for each channel type or lose type safety.
Remember there is no buffering, so if you peek at a value, you'd have to get the value from the other side, which would be equivalent to reading it - but that's wrong because peeking should have no side effects.
You can't really. What you have is the only way, but don't do that if there's any concurrent access to the chan (and then why are you using a chan?).
Items could be inserted or removed after you check len, and during your for loop.
Related
I've wrapped a queue to implement the Writer and Reader interfaces (for pushing and popping, respectively).
I need to continuously listen to the queue, and handle every message that comes through. This is simple when the queue is represented as a channel, but more difficult otherwise:
loop:
for {
var data []byte
select {
case <-done:
break loop
case _, err := queue.Read(data):
fmt.Println(string(data))
}
}
What's the proper way to do this? Read here is blocking - it waits until the queue has a message.
Is there a better, more idiomatic way to achieve this?
It’s harder to take a synchronous API (like queue.Read as you described above) and make it asynchronous than it is to do the opposite.
The idea would be to create a new goroutine (using, for example go func() {...}) and have that goroutine execute the read and write the output to a channel.
Then the first goroutine would block on that channel and the one it’s already blocking on.
This has the potentially to leave orphaned resources for a little while if the read takes to long but if you have a synchronous API, it’s the best you can do.
I'm writing a program in the Go language, and I have a simple problem:
I have some goroutines in my program and channels with which goroutines use to communicate. From time to time I would like to check what is inside the channels. How could I achieve that without interrupting the goroutines' work? Do channels have any function to print their contents? Or should I somehow copy them?
var shelf chan int = make(chan int, 5)
go Depot(shelf)
go Shop(shelf)
var input string
fmt.Scanln(&input)
if (input == "print") {
//here print what on shelf
}
How could I achieve that without interrupting the goroutines' work?
The simple answer is that you can't, without interrupting. Channels are a synchronization primitive, meaning that they are what enables concurrent programs to communicate safely. If you take something out of a channel, that "taking out" happens atomically, nobody else can take the same item out of the same channel. And that's intended.
What you can do is take items out and put them back after printing them. The problem with this approach is that some elements might never be printed while others may be printed more than once as all goroutines involved race to grab items from the channel.
It sounds like you need something else than a channel.
After (briefly) reviewing the Go language spec, effective Go, and the Go memory model, I'm still a little unclear as to how Go channels work under the hood.
What kind of structure are they? They act kind of like a thread-safe queue /array.
Does their implementation depend on the architecture?
The source file for channels is (from your go source code root) in /src/pkg/runtime/chan.go.
hchan is the central data structure for a channel, with send and receive linked lists (holding a pointer to their goroutine and the data element) and a closed flag. There's a Lock embedded structure that is defined in runtime2.go and that serves as a mutex (futex) or semaphore depending on the OS. The locking implementation is in lock_futex.go (Linux/Dragonfly/Some BSD) or lock_sema.go (Windows/OSX/Plan9/Some BSD), based on the build tags.
Channel operations are all implemented in this chan.go file, so you can see the makechan, send and receive operations, as well as the select construct, close, len and cap built-ins.
For a great in-depth explanation on the inner workings of channels, you have to read Go channels on steroids by Dmitry Vyukov himself (Go core dev, goroutines, scheduler and channels among other things).
Here is a good talk that describes roughly how channels are implemented:
https://youtu.be/KBZlN0izeiY
Talk description:
GopherCon 2017: Kavya Joshi - Understanding Channels
Channels provide a simple mechanism for goroutines to communicate, and a powerful construct to build sophisticated concurrency patterns. We will delve into the inner workings of channels and channel operations, including how they're supported by the runtime scheduler and memory management systems.
You asked two questions:
What kind of structure are they?
Channels in go are indeed "kind of like a thread-safe queue", to be more precise, channels in Go have the following properties:
goroutine-safe
Provide FIFO semantics
Can store and pass values between goroutines
Cause goroutines to block and unblock
Every time you create a channel, an hchan struct is allocated on the heap, and a pointer to the hchan memory location is returned represented as a channel, this is how go-routines can share it.
The first two properties described above are implemented similarly to a queue with a lock.
The elements that the channel can pass to different go-routines are implemented as a circular queue (ring buffer) with indices in the hchan struct, the indices account for the position of elements in the buffer.
Circular queue:
qcount uint // total data in the queue
dataqsiz uint // size of the circular queue
buf unsafe.Pointer // points to an array of dataqsiz elements
And the indices:
sendx uint // send index
recvx uint // receive index
Every time a go-routine needs to access the channel structure and modify it's state it holds the lock, e.g: copy elements to/ from the buffer, update lists or an index. Some operations are optimized to be lock-free, but this is out of the scope for this answer.
The block and un-block property of go channels is achieved using two queues (linked lists) that hold the blocked go-routines
recvq waitq // list of recv waiters
sendq waitq // list of send waiters
Every time a go-routine wants to add a task to a full channel (buffer is full), or to take a task from an empty channel (buffer is empty), a pseudo go-routine sudog struct is allocated and the go-routine adds the sudog as a node to the send or receive waiters list accordingly. Then the go-routine updates the go runtime scheduler using special calls, which hints when they should be taken out of execution (gopark) or ready to run (goready).
Notice this is a very simplified explanations that hides some complexities.
Does their implementation depend on the architecture?
Besides the lock implementation that is OS specific as #mna already explained, I'm not aware of any architecture specific constraints optimizations or differences.
A simpler way to look at channels is as such, in that you may like to hold a program up while waiting for a condition to complete, typically used to prevent RACE condition, which means a thread might not finish before another, and then something your later thread or code depends on sometimes does not complete.
An example could be, you have a thread to retrieve some data from a database or other server and place the data into a variable, slice or map, and for some reason it gets delayed. then you have a process that uses that variable, but since it hasn't been initialised, or its not got its data yet. the program fails.
So a simple way to look at it in code is as follows:
package main
import "fmt"
var doneA = make(chan bool)
var doneB = make(chan bool)
var doneC = make(chan bool)
func init() { // this runs when you program starts.
go func() {
doneA <- true //Give donA true
}()
}
func initB() { //blocking
go func() {
a := <- doneA //will wait here until doneA is true
// Do somthing here
fmt.Print(a)
doneB <- true //State you finished
}()
}
func initC() {
go func() {
<-doneB // still blocking, but dont care about the value
// some code here
doneC <- true // Indicate finished this function
}()
}
func main() {
initB()
initC()
}
So hope this helps. not the selected answer above, but i believe should help to remove the mystery. I wonder if I should make a question and self answer?
I'm learning Go and so far very impressed with it. I've read all the online docs at golang.org and am halfway through Chrisnall's "The Go Programming Language Phrasebook". I get the concept of channels and think that they will be extremely useful. However, I must have missed something important along the way, as I can't see the point to one-way channels.
If I'm interpreting them correctly, a read-only channel can only be received on and a write-only channel can only be transmitted on, so why have a channel that you can send to and never receive on? Can they be cast from one "direction" to the other? If so, again, what's the point if there's no actual constraint? Are they nothing more than a hint to client code of the channel's purpose?
A channel can be made read-only to whoever receives it, while the sender still has a two-way channel to which they can write. For example:
func F() <-chan int {
// Create a regular, two-way channel.
c := make(chan int)
go func() {
defer close(c)
// Do stuff
c <- 123
}()
// Returning it, implicitly converts it to read-only,
// as per the function return type.
return c
}
Whoever calls F(), receives a channel from which they can only read.
This is mostly useful to avoid potential misuse of a channel at compile time.
Because read/write-only channels are distinct types, the compiler can use
its existing type-checking mechanisms to ensure the caller does not try to write
stuff into a channel it has no business writing to.
I think the main motivation for read-only channels is to prevent corruption and panics of the channel. Imagine if you could write to the channel returned by time.After. This could mess up a lot of code.
Also, panics can occur if you:
close a channel more than once
write to a closed channel
These operations are compile-time errors for read-only channels, but they can cause nasty race conditions when multiple go-routines can write/close a channel.
One way of getting around this is to never close channels and let them be garbage collected. However, close is not just for cleanup, but it actually has use when the channel is ranged over:
func consumeAll(c <-chan bool) {
for b := range c {
...
}
}
If the channel is never closed, this loop will never end. If multiple go-routines are writing to a channel, then there's a lot of book-keeping that has to go on with deciding which one will close the channel.
Since you cannot close a read-only channel, this makes it easier to write correct code. As #jimt pointed out in his comment, you cannot convert a read-only channel to a writeable channel, so you're guaranteed that only parts of the code with access to the writable version of a channel can close/write to it.
Edit:
As for having multiple readers, this is completely fine, as long as you account for it. This is especially useful when used in a producer/consumer model. For example, say you have a TCP server that just accepts connections and writes them to a queue for worker threads:
func produce(l *net.TCPListener, c chan<- net.Conn) {
for {
conn, _ := l.Accept()
c<-conn
}
}
func consume(c <-chan net.Conn) {
for conn := range c {
// do something with conn
}
}
func main() {
c := make(chan net.Conn, 10)
for i := 0; i < 10; i++ {
go consume(c)
}
addr := net.TCPAddr{net.ParseIP("127.0.0.1"), 3000}
l, _ := net.ListenTCP("tcp", &addr)
produce(l, c)
}
Likely your connection handling will take longer than accepting a new connection, so you want to have lots of consumers with a single producer. Multiple producers is more difficult (because you need to coordinate who closes the channel) but you can add some kind of a semaphore-style channel to the channel send.
Go channels are modelled on Hoare's Communicating Sequential Processes, a process algebra for concurrency that is oriented around event flows between communicating actors (small 'a'). As such, channels have a direction because they have a send end and a receive end, i.e. a producer of events and a consumer of events. A similar model is used in Occam and Limbo also.
This is important - it would be hard to reason about deadlock issues if a channel-end could arbitrarily be re-used as both sender and receiver at different times.
How do I check whether a channel has a value for me to read?
I don't want to block when reading a channel. I want to see whether it has a value. If it does have one, I'll read it. If it doesn't have one (yet), I'll do something else and check back again later.
The only non-blocking operation I know of to read from a channel is inside a select block having a default case :
select {
case x, ok := <-ch:
if ok {
fmt.Printf("Value %d was read.\n", x)
} else {
fmt.Println("Channel closed!")
}
default:
fmt.Println("No value ready, moving on.")
}
Please try the non-blocking here
Note about previous answers: the receive operator itself is now a blocking operation, as of Go 1.0.3 . The spec has been modified. Please try the blocking here (deadlock)
If you're doing this often then it's probably not a great design and you might be better off spawning another goroutine to do whatever work you're planning to do when there isn't anything to read from the channel. The synchronous/blocking nature of Go's channels make code easier to read and reason about while the scheduler and cheap goroutines means that async calls are unnecessary since waiting goroutines take up very little resources.
Unfortunately, the previous answers are incorrect. The spec clearly says that you CAN use channels this way using len() function, but only if you specified the channel capacity - the buffer length for a channel while making it. If you omitted a channel capacity while making it - the channel operations are always blocking.
You don't, at least not for synchronous (unbuffered) channels. There is no way to tell if a value is waiting without asking to take the value from the channel.
For buffered channels, you technically can use the len function to do what you describe, but you really, really shouldn't. Your technique is invalid.
The reason is that it represents a race condition. Given channel ch, your goroutine might see that len(ch) > 0 and conclude that there is a value waiting. It cannot conclude however, that it can read from the channel without blocking--another goroutine might empty the channel between the time you check len and the time your receive operation runs.
For the purpose you described, use select with a default case as Ripounet showed.
WARNING: This is no longer accurate, see the answer below.
From the docs:
If a receive expression is used in an
assignment or initialization of the
form
x, ok = <-ch
x, ok := <-ch
var x, ok = <-ch
the receive operation becomes
non-blocking. If the operation can
proceed, the boolean variable ok will
be set to true and the value stored in
x; otherwise ok is set to false and x
is set to the zero value for its type
In most cases relying on such information is a really bad design choice. Not even saying about how it's dirty in it's implementation.
So, do not implement the following steps to detect if channel is ready for read at runtime:
define hchan waitq sudog structs as defined here - https://golang.org/src/runtime/chan.go
use "unsafe" package to cast channel to pointer to hchan struct
read sendq field of this struct to get listeners
read first sudog and read msg field from there.
cast msg to the appropriate type for the channels using "reflect" and "unsafe"