In our first part, we covered basic goroutines and channels. In this part, we will focus on how to write data into channels and range over the channels.
In this part we will cover reading, writing into channels, and ranging over the channels.
For simplicity, we will make a message channel and let others read the data from the channel. I hope you know the channel will block leading to deadlock if it is full. That also means if you are reading faster than you are writing also it will lead to deadlock.
let's make msgch := make(chan string, number). Your number value depends on the ability to read from the channel. If you are reading faster than you are writing.
Here, we create mgsch (message channel) and write A, B, and C into the channels. and reading the cha
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main
import (
"fmt"
)
func main() {
msgch:= make (chan string, 128)
msgch <- "A"
msgch <- "B"
msgch <- "C"
Rmsg := <-msgch
fmt.Println(Rmsg)
}
The output for this will be go run main.go
A
That means it will read a single message at one time. So either we have to read one message at a time and console each other. But that is not the appropriate way to run the program.
In the above example, we have written 3 messages to the channel and we have to range over the channel to read each message. For example:
for msg := range msgch {
fmt.Println(“the message—>,”msg)
}
The problem is we are ranging over the message so how will the compiler know that we have stopped writing messages to our tunnel? (Channel) If we run this code we will end up having an ERROR.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
import (
"fmt"
)
func main() {
msgch := make(chan string, 128)
msgch <- "A"
msgch <- "B"
msgch <- "C"
for Rmsg := range msgch {
fmt.Println(Rmsg)
}
}
Output
go run main.go
A
B
C
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
Therefore, to avoid such errors we have to close the channel after writing close(msgch). Now it will run perfectly. Below is the code and output for the same.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
import (
"fmt"
)
func main() {
msgch := make(chan string, 128)
msgch <- "A"
msgch <- "B"
msgch <- "C"
close(msgch)
for Rmsg := range msgch {
fmt.Println(Rmsg)
}
}
Output:
go run main.go
A
B
C
The alternative way. When we range over the loop it is working perfectly. However, if we implement the for loop then it will continue as we don’t have information to break. Therefore the code for implementing the same for the loop is below. While reading the channel if the channel is complete it returns a boolean value.
Rmsg, ok := <-msgch
If ! ok {
break
}
fmt.println(Rmsg)
Below is the code and the output of for loop.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main
import (
"fmt"
)
func main() {
msgch := make(chan string, 128)
msgch <- "A"
msgch <- "B"
msgch <- "C"
close(msgch)
for {
Rmsg, ok := <-msgch
if !ok {
break
}
fmt.Println(Rmsg)
}
}
Output:
go run main.go
A
B
C
Check the source code in the linked repository.
https://github.com/GolangCompany/go-concurrency-part02
In this blog, we have covered how to write to a channel, read over the channel, range over the channel, and errors when we don’t close the channel. If you have any doubts feel free to contact our golang developers. If you are having a Go project and want our team to help we are happy to assist the same.