2. Programlama Dilleri
Aktif olarak Go ile geliştirme yapmakla
birlikte uzun yıllar PHP backend
developer olarak proje geliştirdim.
İletişim Bilgisi
Eposta : yakuter@gmail.com
Twitter: @yakuter
İş / Görev
Binalyze isimli Enterprise Forensics
yazılım şirketinde Senior Software
Architect olarak çalışmaktayım.
Tecrübe/Bilgi
Yaklaşık 15+ yıldır yazılım geliştirme ile
ilgilenmekte olup, şu anda işletim
sistemleri üzerinde olay sonrası delillerin
toplanması için yazılım geliştirmekteyim.
Erhan YAKUT
(yakuter)
Biyografi
Ben Kimim?
3. Why do we need channels?
Goroutines need to communicate each other to synchronize or exchange data with
each other. The solution is channels.
4. What is channel?
Channels are the pipes that connect concurrent
goroutines. You can send values into channels from one
goroutine and receive those values into another
goroutine.
Channels are a typed conduit through which you can
send and receive values with the channel operator, <-.
ch <- v // Send v to channel ch.
v := <-ch // Receive from ch, and assign value to v.
(The data flows in the direction of the arrow.)
Like maps and slices, channels must be created before
use:
ch := make(chan int)
5. Closing channels
Senders have the ability to close the channel to notify
receivers that no more data will be sent on the channel.
Receivers can use an additional variable while receiving
data from the channel to check whether the channel has
been closed.
v, ok := <- ch
If ok is false it means that we are reading from a closed
channel.
The value read from a closed channel will be the zero
value of the channel's type. For example, if the channel is
an int channel, then the value received from a closed
channel will be 0.
Only the sender should close a channel, never the
receiver. Sending on a closed channel will cause a panic.
6. Buffered channels and range
It is possible to create a channel with a buffer. Sends to a
buffered channel are blocked only when the buffer is full.
Similarly receives from a buffered channel are blocked
only when the buffer is empty.
Buffered channels can be created by passing an
additional capacity parameter to the make function
which specifies the size of the buffer.
ch := make(chan type, capacity)
The loop for v := range ch receives values from the
channel repeatedly until it is closed.
7. Worker pool
In computer programming, a worker pool is a software
design pattern for achieving concurrency of execution in
a computer program.
A worker pool maintains multiple threads waiting for
tasks to be allocated for concurrent execution by the
supervising program.
8. Select usage
The select statement is used to choose from multiple
send/receive channel operations. The select statement
blocks until one of the send/receive operations is ready. If
multiple operations are ready, one of them is chosen at
random.
The syntax is similar to switch except that each of the
case statements will be a channel operation.
9. Check context with select and ticker
Tickers are for when you want to do something
repeatedly at regular intervals.
Tickers use a similar mechanism to timers: a channel that
is sent values.
In the example, we’ll use the select builtin on the channel
to await the values as they arrive every interval.
10. Channels for notification
1-to-1 notification
Notifications can be viewed as special requests/responses
in which the responded values are not important.
Generally, we use the blank struct type struct{} as the
element types of the notification channels, for the size of
type struct{} is zero, hence values of struct{} doesn't
consume memory.
11. Start/stop signal
If we queue up lots of goroutines, we can have them all
start at the same time by closing the signal channel.
12. Start/stop signal with waitgroup
To wait for multiple goroutines to finish, we can use a
wait group.
This WaitGroup is used to wait for all the goroutines
launched here to finish. Note: if a WaitGroup is explicitly
passed into functions, it should be done by pointer.
Launch several goroutines and increment the WaitGroup
counter for each.
Avoid re-use of the same i value in each goroutine
closure.
https://go.dev/doc/faq#closures_and_goroutines
13. Scheduled notification
We can use a timer or sleep function to wait for desired
time and then send signal (notification)
Please note, <-time.After(aDuration) will make the
current goroutine enter blocking state, but a
time.Sleep(aDuration) function call will not.
The use of <-time.After(aDuration) is often used in the
timeout mechanism which will be introduced below.
14. Use channels as mutex locks
Channels are blocking actions. So we can use them as
mutex locks.
There are two manners to use one-capacity buffered
channels as mutex locks.
- Lock through a send, unlock through a receive.
- Lock through a receive, unlock through a send.
The following is a lock-through-send example.
15. Use channels as multi access mutexes
Buffered channels can be used as multi access mutexes.
If the capacity of a channel is N, then it can be viewed as
a lock which can have most N owners at any time.
Counting semaphores are often used to enforce a
maximum number of concurrent requests.