Dmitry Telenkov 1 개월 전
부모
커밋
0ef8de5e47
1개의 변경된 파일166개의 추가작업 그리고 0개의 파일을 삭제
  1. 166 0
      go/habr/channel_anatomy.go

+ 166 - 0
go/habr/channel_anatomy.go

@@ -0,0 +1,166 @@
+package main
+
+import (
+	"fmt"
+	"runtime"
+	"time"
+)
+
+/*
+1. Буферизированный канал.
+c := make(chan int, 5)
+
+Операция чтения такого канала является жадной, т.к. горутина чтения не будет
+блокироваться до тех пор пока не будет вычетан весь буфер.
+При записи в канал действует та же логика.
+
+*/
+
+func squares(c chan int) {
+	for i := 0; i <= 9; i++ {
+		c <- i * i
+	}
+	close(c)
+}
+
+func main() {
+	// foo1()
+	// capChannel()
+	// runtimeChannel()
+	readAfterClose()
+	/*
+		fmt.Println("main() started")
+		c := make(chan int)
+
+		go squares(c)
+
+		// range будет считывать данные из канала пока он не будет закрыт
+		// Если в squares не будет close, то будет deadlock
+		for val := range c {
+			fmt.Println(val)
+		}
+
+		fmt.Println("main() stopped")
+	*/
+
+	/*
+		for {
+			val, ok := <-c
+			if ok == false {
+				fmt.Println(val, ok, "<-- loop broke!")
+				break // exit break loop
+			} else {
+				fmt.Println(val, ok)
+			}
+		}
+	*/
+}
+
+func squaresRead(c chan int) {
+	for i := 0; i <= 3; i++ {
+		num := <-c
+		fmt.Println(num * num)
+	}
+}
+
+// Буферизированный канал не будет блоикироваться при записи
+func foo1() {
+	fmt.Println("main() started")
+	c := make(chan int, 3)
+
+	go squaresRead(c)
+
+	c <- 1
+	c <- 2
+	c <- 3
+	c <- 4
+	// c <- 5
+	// c <- 6
+	// c <- 7
+	// c <- 8
+	// c <- 9
+	// c <- 10
+
+	// time.Sleep(1 * time.Second)
+	fmt.Println("main() stopped")
+}
+
+// -----------------------------------------------------------------
+
+func sender(c chan int) {
+	c <- 1
+	c <- 2
+	c <- 3
+	c <- 4 // goroutine blocks here
+	close(c)
+}
+
+func capChannel() {
+	c := make(chan int, 3)
+	go sender(c)
+	fmt.Printf("Length and capacity of channel c is %v, %v\n", len(c), cap(c))
+
+	// read values from c (blocked here)
+	for val := range c {
+		fmt.Printf("Length of channel c after value '%v' len is %v\n", val, len(c))
+	}
+
+}
+
+// -----------------------------------------------------------------
+
+func squaresFour(c chan int) {
+	for i := 0; i < 4; i++ {
+		num := <-c
+		fmt.Println(num * num)
+	}
+}
+
+func runtimeChannel() {
+	fmt.Println("main() started")
+	c := make(chan int, 3)
+	go squaresFour(c)
+
+	fmt.Println("active goroutines", runtime.NumGoroutine())
+
+	c <- 1
+	c <- 2
+	c <- 3
+	c <- 4 // bloks here
+
+	time.Sleep(1 * time.Second)
+
+	fmt.Println("active goroutines", runtime.NumGoroutine())
+
+	go squaresFour(c)
+
+	fmt.Println("active goroutines", runtime.NumGoroutine())
+
+	c <- 5
+	c <- 6
+	c <- 7
+	c <- 8 // bloks here
+
+	fmt.Println("active goroutines", runtime.NumGoroutine())
+	fmt.Println("main() stopped")
+}
+
+// -----------------------------------------------------------------
+
+func readAfterClose() {
+	c := make(chan int, 3)
+	c <- 1
+	c <- 2
+	c <- 3
+	close(c)
+	/*
+		for elem := range c {
+			fmt.Println(elem)
+		}
+	*/
+
+	// Так тоже не будет deadlock
+	for i := 0; i < 5; i++ {
+		fmt.Println(i, <-c)
+	}
+}