Go by Example (上 桷)

Github code: github.com/ftopia2020/…

The following are only basic syntax examples of Go concurrency. These are far from enough. You need to systematically study its concepts and theories, read a lot of relevant materials and practice and understand the classic Go concurrency mode to master the essence of Go concurrency programming.


  • Do not communicate by sharing memory; instead, share memory by communicating.
  • Don’t communicate by sharing memory. Communicate by sharing memory.

Keep in mind the above classic “Go concurrent philosophy” (it doesn’t matter if you don’t understand it), and keep trying to apply it will make you better understand “Go concurrent philosophy”.

22 Goroutines

When we run this program, the result may be different each time we run it, such as the screenshot going printed after f(“goroutine”)

It could be an alternate output of two coroutines. This alternation indicates that the Go Runtime runs the coroutine concurrently

$ go run goroutines.go
direct : 0
direct : 1
direct : 2
goroutine : 0
going
goroutine : 1
goroutine : 2
done
Copy the code

For cooutines just learning Go, you can block main using time.sleep to give other coroutines a chance to run completely, but note that this is not recommended (it is better to use WaitGroup).

Extended thinking

Change the order of time.sleep and run it more times. Why is the result different? (Sometimes the Goroutine executes, sometimes it doesn’t, sometimes it’s half done.)

The entry point to a Go program is usually the main function, which runs main Goroutine first when the program starts

The go + func() method is used to start the coroutine only in main or code called below it.

Func main() is the main thread. When main completes, the thread terminates and all running coroutines exit, regardless of whether the code is still running.

23 Channels

24 Channel Buffering

25 Channel Synchronization

The above example uses blocking reception to wait for another coroutine to complete

If you need to wait for multiple coroutines, WaitGroup is a better choice

Try commenting <-done and the program may end before the worker starts

26 Channel Directions

27 Select

Select is similar to the switch statement used for communication and is used with case

  • Case must be a communication operation, write/read
  • Support default (not shown in this example, ↓ will provide relevant examples)

28 Timeouts

  • While waiting, timeout cases are executed only when the wait is complete, during which the SELECT waits for all cases
  • In the above waiting process (such as 1, 3s waiting), other cases also continue

29 Non-blocking Channel Operations

Extended thinking

What is printed if you uncomment the coroutine for both comments and run it again? What if you do not add the timeout time.after?

Coroutine concurrency, not sure which channel receives first, so it’s random

If it is not blocked, default takes precedence

30 Closing Channels

Try writing a value to the closed channel

31 Range Over Channels

32 Timers

33 Ticker

34 Worker Pools

Think about it, why is the total 2s or so? If you rewrite the time.Sleep in worker to 2s, how many seconds will it run in total?

35 Waitgroups

What would happen if YOU commented out WG.wait ()?

For understanding and using defer, refer to resources such as golang.org/ref/spec#De…

There will be a follow-up example of defer in the next article

36 Rate Limiting

Rate limiting is an important mechanism for controlling service resource utilization and quality. Go elegantly supports rate limiting based on coroutines, channels, and punters

Running the program, we see that the first requests are processed about every 200ms

The second batch of Burst requests (Burst Requests) can be observed, with 3 requests appearing instantly, and then the remaining 3 requests are processed every 500ms

2500 = 200Γ—5 + 500Γ—3

37 Atomic Counters

Get a feel for the speed of Go concurrency πŸš€ print 1000Γ—50 = 50000

38 Mutexes

For more complex cases, we can use a * mutexes * to securely access data between Go coroutines

39 Stateful Goroutines

Shared state is accessed synchronously across multiple Goroutines, in line with the Go concurrency philosophy of “Shared memory through communication”

From this example we can see that the coroutine based approach is much more complex than the mutex based approach. However, it can be useful in some situations, such as when you are dealing with other channels, or when managing multiple mutexes of the same kind, where it is easy to make mistakes. You should use the most natural approach, especially in understanding program correctness.

Next

The above example shows the charm of Golang concurrency

Beginners or those with a weak foundation in concurrent programming will struggle to understand, so keep going πŸ’ͺ

In the next installment, there are some examples of specific Golang development scenarios, including the following:

  • Some common methods for built-in packages (e.g., sort, time, IO, OS, FMT, etc.)
  • Panic
  • Defer
  • Unit testing
  • Command line operation
  • HTTP based
  • Build process/execute process
  • signal
  • exit