Channels are data structures that enable safe data communication between goroutines. Channels help you to avoid problems typically seen in programming languages that allow shared memory access.
The hardest part of concurrency is ensuring that your data isn’t unexpectedly modified by concurrently running processes, threads, or goroutines. When multiple threads change the same data without locks or synchronization, heartache always follows. In other languages, when you have global variables and shared memory, you’re required to use complicated locking disciplines to prevent unsynchronized changes to the same variables.
Channels help to solve this problem by providing a pattern that makes data safe from concurrent modification. Channels help to enforce the pattern that only one goroutine should modify the data at any time.