├── .vscode └── settings.json ├── 01-what-is-channel └── main.go ├── 02-closing-channel └── main.go ├── 03-buffered-channel └── main.go ├── 04-worker-pool └── main.go ├── 05-select └── main.go ├── 06-context-select └── main.go ├── 07-signalling └── main.go ├── 08-start-stop-signal └── main.go ├── 09-waitgroup └── main.go ├── 10-scheduled-signal └── main.go ├── 11-mutex-channels └── main.go ├── 12-multi-access-mutexes └── main.go ├── 13-is-closed └── main.go ├── README.md └── go.mod /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.rulers": [60,120], 3 | } -------------------------------------------------------------------------------- /01-what-is-channel/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | 7 | messages := make(chan string) 8 | 9 | go func() { messages <- "ping" }() 10 | 11 | msg := <-messages 12 | fmt.Println(msg) 13 | } 14 | 15 | // Output 16 | // ping 17 | -------------------------------------------------------------------------------- /02-closing-channel/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func producer(chnl chan int) { 8 | for i := 0; i < 10; i++ { 9 | chnl <- i 10 | } 11 | close(chnl) 12 | } 13 | 14 | func main() { 15 | ch := make(chan int) 16 | go producer(ch) 17 | 18 | for { 19 | v, ok := <-ch 20 | if ok == false { 21 | break 22 | } 23 | fmt.Println("Received ", v, ok) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /03-buffered-channel/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func producer(ch chan int) { 9 | for i := 0; i < 10; i++ { 10 | ch <- i 11 | fmt.Println("wrote", i, "to ch") 12 | } 13 | close(ch) 14 | } 15 | func main() { 16 | ch := make(chan int, 4) 17 | go producer(ch) 18 | time.Sleep(2 * time.Second) 19 | 20 | for v := range ch { 21 | fmt.Println("read ", v, "from ch") 22 | time.Sleep(2 * time.Second) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /04-worker-pool/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func worker(id int, jobs <-chan int, results chan<- int) { 9 | for j := range jobs { 10 | fmt.Println("worker", id, "started job", j) 11 | time.Sleep(time.Second) 12 | fmt.Println("worker", id, "finished job", j) 13 | results <- j * 2 14 | } 15 | } 16 | 17 | func main() { 18 | 19 | const numJobs = 5 20 | jobs := make(chan int, numJobs) 21 | results := make(chan int, numJobs) 22 | 23 | for w := 1; w <= 3; w++ { 24 | go worker(w, jobs, results) 25 | } 26 | 27 | for j := 1; j <= numJobs; j++ { 28 | jobs <- j 29 | } 30 | close(jobs) 31 | 32 | for a := 1; a <= numJobs; a++ { 33 | <-results 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /05-select/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func process(ch chan string) { 9 | time.Sleep(5500 * time.Millisecond) 10 | ch <- "The secret of the world: 42" 11 | } 12 | 13 | func main() { 14 | ch := make(chan string) 15 | go process(ch) 16 | for { 17 | time.Sleep(1000 * time.Millisecond) 18 | select { 19 | case v := <-ch: 20 | fmt.Println("received value: ", v) 21 | return 22 | default: 23 | fmt.Println("no value received") 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /06-context-select/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "time" 8 | ) 9 | 10 | const interval = 500 11 | 12 | func main() { 13 | ctx, cancel := context.WithCancel(context.Background()) 14 | go func() { 15 | time.Sleep(5 * interval * time.Millisecond) 16 | fmt.Println("cancelling context from 5 seconds") 17 | cancel() 18 | }() 19 | f(ctx) 20 | } 21 | 22 | func f(ctx context.Context) { 23 | ticker := time.NewTicker(interval * time.Millisecond) 24 | for { 25 | select { 26 | case <-ticker.C: 27 | doSomething() 28 | case <-ctx.Done(): 29 | return 30 | } 31 | } 32 | } 33 | 34 | func doSomething() { log.Println("tick") } 35 | -------------------------------------------------------------------------------- /07-signalling/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | "os" 7 | "sort" 8 | ) 9 | 10 | func main() { 11 | values := make([]byte, 32*1024*1024) 12 | if _, err := rand.Read(values); err != nil { 13 | fmt.Println(err) 14 | os.Exit(1) 15 | } 16 | 17 | done := make(chan struct{}) 18 | 19 | // The sorting goroutine 20 | go func() { 21 | sort.Slice(values, func(i, j int) bool { 22 | return values[i] < values[j] 23 | }) 24 | // Notify sorting is done. 25 | fmt.Println("tamamlandi") 26 | done <- struct{}{} 27 | }() 28 | 29 | // do some other things ... 30 | 31 | <-done // waiting here for notification 32 | fmt.Println(values[0], values[len(values)-1]) 33 | } 34 | -------------------------------------------------------------------------------- /08-start-stop-signal/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func main() { 9 | start := make(chan struct{}) 10 | for i := 0; i < 10000; i++ { 11 | go func(k int) { 12 | <-start // wait for the start channel to be closed 13 | fmt.Println(k) 14 | }(i) 15 | } 16 | 17 | time.Sleep(3 * time.Second) 18 | 19 | close(start) 20 | } 21 | -------------------------------------------------------------------------------- /09-waitgroup/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | 11 | var wg sync.WaitGroup 12 | 13 | start := make(chan struct{}) 14 | for i := 0; i < 10000; i++ { 15 | wg.Add(1) 16 | go func(count int) { 17 | defer wg.Done() 18 | <-start // wait for the start channel to be closed 19 | fmt.Println(count) 20 | }(i) 21 | } 22 | 23 | time.Sleep(3 * time.Second) 24 | 25 | // at this point, all goroutines are ready to go - we just need to 26 | // tell them to start by closing the start channel 27 | close(start) 28 | 29 | wg.Wait() 30 | } 31 | -------------------------------------------------------------------------------- /10-scheduled-signal/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func AfterDuration(d time.Duration) <-chan struct{} { 9 | c := make(chan struct{}, 1) 10 | go func() { 11 | time.Sleep(d) 12 | c <- struct{}{} 13 | }() 14 | return c 15 | } 16 | 17 | func main() { 18 | fmt.Println("Hi!") 19 | <-AfterDuration(time.Second) 20 | fmt.Println("Hello!") 21 | <-AfterDuration(time.Second) 22 | fmt.Println("Bye!") 23 | 24 | <-time.After(time.Second) 25 | fmt.Println("Last") 26 | } 27 | -------------------------------------------------------------------------------- /11-mutex-channels/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // The capacity must be one. 7 | mutex := make(chan struct{}, 1) 8 | 9 | counter := 0 10 | increase := func() { 11 | mutex <- struct{}{} // lock 12 | counter++ 13 | <-mutex // unlock 14 | } 15 | 16 | increase1000 := func(done chan<- struct{}) { 17 | for i := 0; i < 1000; i++ { 18 | increase() 19 | } 20 | done <- struct{}{} 21 | } 22 | 23 | done := make(chan struct{}) 24 | go increase1000(done) 25 | go increase1000(done) 26 | <-done 27 | <-done 28 | fmt.Println(counter) // 2000 29 | } 30 | -------------------------------------------------------------------------------- /12-multi-access-mutexes/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | type Seat int 10 | type Bar chan Seat 11 | 12 | func (bar Bar) ServeCustomer(c int) { 13 | log.Print("customer#", c, " enters the bar") 14 | seat := <-bar // need a seat to drink 15 | log.Print("++ customer#", c, " drinks at seat#", seat) 16 | time.Sleep(time.Second * time.Duration(2+rand.Intn(6))) 17 | log.Print("-- customer#", c, " frees seat#", seat) 18 | bar <- seat // free seat and leave the bar 19 | } 20 | 21 | func main() { 22 | rand.Seed(time.Now().UnixNano()) 23 | 24 | // the bar has 10 seats. 25 | bar24x7 := make(Bar, 3) 26 | // Place seats in an bar. 27 | for seatId := 0; seatId < cap(bar24x7); seatId++ { 28 | // None of the sends will block. 29 | bar24x7 <- Seat(seatId) 30 | } 31 | 32 | for customerId := 0; ; customerId++ { 33 | time.Sleep(time.Second) 34 | go bar24x7.ServeCustomer(customerId) 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /13-is-closed/main.go: -------------------------------------------------------------------------------- 1 | func IsClosed(c chan T) bool { 2 | select { 3 | case <-c: 4 | return true 5 | default: 6 | } 7 | return false 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # channels-use-cases 2 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/yakuter/channels-use-cases 2 | 3 | go 1.17 4 | --------------------------------------------------------------------------------