zoukankan      html  css  js  c++  java
  • Golang东北之旅—channel

    [本文出自天外归云的博客园]

    本文借一段斐波那契函数golang版代码讲下golang中四个核心的东西:channel(通道/管道/下水道/啥道都行,咋方便咋记)、go func(){}()(异步执行函数)、<-(阻塞式等待/死等/等不着不行就等/干等/干靠/靠到有东西为止)、for-select-case(循环选择,for是死循环的还,所以这个是个无限循环等待)

    题外话,学以致用,你都不知道这玩意是干啥用的,你学他干啥?我告诉你这玩意有啥用,我打个比方哈,就好比吧,你每天都重复相同的过程:除了上班儿就是睡大觉,那么我们说这个过程,就可以用上面这四个东西描述出来:

    func TestYourLife(t *testing.T) {
    	var currentHour = make(chan int)
    	go func() {
    		for true {
    			time.Sleep(time.Duration(2) * time.Second)
    			currentHour <- time.Now().Hour()
    		}
    	}()
    	for {
    		select {
    		case hour := <-currentHour:
    			if hour < 21 {
    				fmt.Println("上班")
    			}
    		case hour := <-currentHour:
    			if hour < 9 {
    				fmt.Println("睡觉")
    			}
    		}
    	}
    } 

    言归正传,读懂下面这段代码,这四个东西你就知道咋回事儿了:

    package main
    
    import "fmt"
    
    func fibonacci(c, quit chan int) {
    	x, y := 0, 1
    	for {
    		select {
    		case c <- x:
    			x, y = y, x+y
    		case <-quit:
    			fmt.Println("quit")
    			return
    		}
    	}
    }
    
    func main() {
    	c := make(chan int)
    	quit := make(chan int)
    	go func() {
    		for i := 0; i < 10; i++ {
    			fmt.Println(<-c)
    		}
    		quit <- 0
    	}()
    	fibonacci(c, quit)
    }
    

    这里就俩函数儿,斐波那契函数儿和main函数儿,main函数是入口儿,所以从main函数儿开始看。

    首先创建了一个变量c,这是个channel,channel就是golang里的一个核心的东西,翻译成中文叫通道,make东北话就是整的意思,int是整型,所以第一行的意思就是:整了一个整型的通道c

    同理,第二行就是:整了一个整型的通道quit

    下面这个go func()也是golang里一个核心的东西,go可以理解为异步执行,func是函数,连起来读就是:异步执行函数

    函数的内容是什么呢?太简单了,for循环,从0-9执行10次,打印的是啥,这块是个难点

    <-c这是啥呢?这是golang里的一个核心的东西,c我们已经知道了是通道

    <-从表面上看是个向左的箭头(没有向右的,所以很好记),这个向左的箭头代表着阻塞式等待,这个箭头如果指向通道(c<-),那就是等待通道有东西放入;如果箭头从通道向外指(<-c),那就是等待通道有东西可取

    因为<-代表着阻塞式等待,所以这个for循环就是死等。又因为go func是异步执行,所以现在斐波那契函数已经开始执行了,我们向下看

    斐波那契函数入参是上面定义的两个通道,一个c一个quit,函数里第一行定义了两个变量x和y

    然后就是一个for-select-case,这是golang里的一个核心的东西,直译就是循环(for)-选择(select)-情况(case)

    看看这俩情况(case)

    第一种情况:等待通道c有x放入

    第二种情况:等待通道quit有东西可取

    那么好,现在x是有值的啊,所以通道c是有东西放入的,你把x扔到管道c了。这个时候非常关键,因为接下来有两件事要做了:

    第一件事是x, y = y, x+y,这是斐波那契数列的定义,把y和x+y的值赋给x和y,关键是另外一件事,异步执行函数中阿豪等着从管道拿东西呢,你现在把x扔到管道c了,阿豪正好拿着了,阿豪拿到x以后,所在for循环继续执行

    重复这个过程10次之后for循环结束,然后接着你就往quit通道里扔了个0,你真行!斐波那契函数for-select-case第二种情况正好满足,于是刚子把东西从quit里取出来了,打印了一句“quit”之后就return退出斐波那契函数了

    本文引用的代码原文所在地:https://tour.golang.org/concurrency/5

  • 相关阅读:
    Topcoder 11351 TheCowDivOne
    Topcoder 14531 Softmatch
    Topcoder 13503 ConnectingGame
    CS Academy Round#5 E.Binary Matching
    洛谷 P5896 [IOI2016]aliens
    P5020 [NOIP2018 提高组] 货币系统
    P1868 饥饿的奶牛
    P3131 [USACO16JAN]Subsequences Summing to Sevens S
    P3959 [NOIP2017 提高组] 宝藏
    2021 Grade 8 whk Final-Test.(Summer) 复**况 & 文明观猴
  • 原文地址:https://www.cnblogs.com/LanTianYou/p/14768055.html
Copyright © 2011-2022 走看看