golang中的goroutine、channel、select简单运用

关闭channel:

package main

import "fmt"

//close();关闭channel
func main() {
	c := make(chan int)

	go func() {
		for i := 0; i < 5; i++ {
			c <- i
		}
		//关闭channel
		close(c)
	}()

	//如果没有关闭channel会死锁
	//for {
	//	//ok如果为true表示channel没有关闭,如果为false则表示channel已关闭
	//	if data, ok := <-c; ok {
	//		fmt.Println("data = ", data)
	//	} else {
	//		break
	//	}
	//}

	//使用range来迭代不断操作channel
	//range 函数遍历每个从通道接收到的数据,因为 c 在发送完 5 个
	//数据之后就关闭了通道,所以这里我们 range 函数在接收到 5 个数据,之后就结束了
	//如果上面的 c 通道不关闭,那么 range 函数就不
	//会结束,从而在接收第 6 个数据的时候就阻塞了,会造成死锁
	for data := range c {
		fmt.Println("data = ", data)
	}

	fmt.Println("main Finished..")
}

输出:

data =  0
data =  1
data =  2
data =  3
data =  4
main Finished..

select应用:

package main

import "fmt"

func fib(c, quit chan int) {
	x, y := 1, 1
	for {
		select {
		case c <- x: //如果c可写就会进来,死循环,向管道内放入x
			x, y = y, x+y
			//x = 1,y=1
			//x = 1,y=2
			//x = 2,y =3
			//x = 3,y = 5
			//x = 5,y = 8
			//x = 8,y = 13
		case data := <-quit: //如果quit通道可以读,代表for循环执行结束,quit中被插入了一个0
			fmt.Println("data = ", data, "退出")
			return
		}
	}
}

//使用select监听多个channel状态
func main() {
	c := make(chan int)
	quit := make(chan int)

	//sub go
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println(<-c) ////打印c通道内的内容
		}

		//退出
		quit <- 0
	}()

	fib(c, quit)
	
}

输出:
1
1
2
3
5
8
13
21
34
55
data =  0 退出

判断通道是否被关闭,我们通常使用的是for range:

package main

import "fmt"
func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    // 开启goroutine将0~100的数发送到ch1中
    go func() {
        for i := 0; i < 10; i++ {
            ch1 <- i
        }
        close(ch1)
    }()
    // 开启goroutine从ch1中接收值,并将该值的平方发送到ch2中
    go func() {
        for {
            i, ok := <-ch1 // 通道关闭后再取值ok=false
            if !ok {
                break
            }
            ch2 <- i * i
        }
        close(ch2)
    }()
    // 在主goroutine中从ch2中接收值打印
    for i := range ch2 { // 通道关闭后会退出for range循环
        fmt.Println(i)
    }
}

zed
请先登录后发表评论
  • latest comments
  • 总共0条评论