Goroutine&Channel

99 阅读2分钟
package main

import "fmt"

func f1(ch chan int) {
	for i:=0;i<10;i++{
		ch<-i
	}
	close(ch)
}

func f2(ch1 chan int, ch2 chan int) {
	for {
		data, ok := <-ch1
		if !ok {
			break
		}
		ch2<-data*data
	}
	close(ch2)
}

func main() {
	ch1 := make(chan int)
	ch2 := make(chan int)
	
	go f1(ch1)
	go f2(ch1, ch2)
	
	for res := range ch2{
		fmt.Println(res)
	}
}

channel

无缓冲通道

package main

import "fmt"

func main() {
	// 无缓冲的通道,在放入数据的同时就需要有一个goroutine把数据取走才可以
	ch := make(chan int)

	go func() {
		ch <- 3
	}()

	fmt.Println(<-ch)
}

有缓冲通道

package main

import "fmt"

func main() {
	// 有缓冲的通道,可以存放指定数量的数据,在存储空间未满的时候不需要同时取出
	ch := make(chan int, 3)
	ch <- 5
	ch <- 88
	ch <- 29

	fmt.Println(<-ch)
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}

单向通道

package main

import "fmt"

// 单向通道,只能往通道里面放入数据
func func1(ch1 chan<- string, msg string) {
	ch1<- msg
}

// 单向通道,只能取通道数据
func func2(ch1 <-chan string) {
	fmt.Println(<-ch1)
}

func main() {
	ch := make(chan string, 1)

	func1(ch, "hello")
	func2(ch)
}

遍历通道/通道关闭

package main

import "fmt"

func main() {
	ch := make(chan int, 10)
	for i:=0;i<10;i++ {
		ch <- i
	}

	// 关闭后通道将不能再往里写入数据了,读是可以的
	close(ch)

	// 使用for遍历通道需要在之前把通道关闭,不然for循环不知道遍历到哪里

	for v := range ch {
		fmt.Println(v)
	}
}

使用通道实现同步

package main

import "fmt"

func worker(flag chan bool) {
	fmt.Println("hello world")
	flag <- true
}

func main() {
	flag := make(chan bool)
	go worker(flag)

	<- flag
}

实现等待多个goroutine

package main

import "fmt"

func worker(flag chan bool) {
	fmt.Println("hello world")
	flag <- true
}

func main() {
	flag := make(chan bool, 3)
	go worker(flag)
	go worker(flag)
	go worker(flag)

	for i:=0; i<3; i++ {
		<- flag
	}
}

channel & goroutine运行逻辑个人分析

package main

import "fmt"

func main() {
	ch := make(chan int, 5)
	go func() {
		for i:=0;i<5;i++ {
			ch <- i
		}
	}()

	for i:=0;i<5;i++{
		// 首先程序来到这里会阻塞住程序,这时去执行其它goroutine,也就是上面的匿名函数
		// 匿名函数执行完毕后这边的阻塞也就会结束,继续执行,从channel中把数据取出来
		fmt.Println(<-ch)
	}
}