• golang channel


    ex1

    package main
    /*
    goroutine 是由GO运行时管理的轻量级线程
    go f(x,y, z) 就启动了一个goroutine, 其中f,x,y,z在当前goroutine中立即计算, f内容的执行在另一个新goroutine中。
    所有的goroutine都是运行在同一个地址空间中, 所有访问共享内存时,必须进行同步处理。
    在sync包中上, 提供了同步需要的原语
    */
    import (
    	"fmt"
    	"time"
    )
    
    func say(s string) {
    	for i := 0; i < 5; i++ {
    		time.Sleep(100 * time.Millisecond)
    		fmt.Println(s)
    	}
    }
    
    func main() {
    	go say("world")
    	say("hello")
    }
    
    

    ex2

    package main
    
    
    /*
    Channels 就管道,就是剧导管, 你可能管道操作符进行读写, 操作符为 <-
    ch <- v    // 把 v 写入管道
    v := <-ch  // 从 ch 管道中读出到 v 变量中
    数据的流向, 就箭头的指向。
    所有 maps , slices, channels 复杂结构都需要通过make来创建
    ch := make (chan int)
    默认情况下, 发收都需要对端准备好了才行, 这样的前提使得goroutine同步就不需要显式的锁处理,降低了复杂度,简化的设计。
    
    下面示例代码, 对slice的值求和。 分布式的工作在两个goroutine中。当其两个完成计算时,最终结果也计算出来了
    */
    
    import "fmt"
    
    func sum(s []int, c chan int) {
    	sum := 0
    	for _, v := range s {
    		sum += v
    	}
    	c <- sum // send sum to c
    }
    
    func main() {
    	s := []int{7, 2, 8, -9, 4, 0}
    
    	c := make(chan int)
    	go sum(s[:len(s)/2], c)
    	go sum(s[len(s)/2:], c)
    	x, y := <-c, <-c // receive from c
    
    	fmt.Println(x, y, x+y)
    }
    
    

    ex3

    /*
    Channels 就管道
    导管通过第二个参数,是可以指定其缓存长度的
    ch := make(chan int, 100)
    当管道满时, 发送会阻塞
    当管道空时, 接收会阻塞
    
    修改下面的代码,可以进行测试一下
    */
    
    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    // 例1、写阻塞等待
    func put_chan(ch chan int, n int)  {
    	for i := 0 ; i < n;  i++{
    		fmt.Println("put: ", i, time.Now().UTC())
    		ch <- i
    	}
    	close(ch)
    }
    
    func read_chan(ch chan int, quit chan int)  {
    	for c := range ch{
    		time.Sleep(time.Duration(time.Second * 3))
    		fmt.Println(c, time.Now().UTC())
    	}
    	time.Sleep(time.Duration(time.Second * 3))
    	quit <- 1
    }
    func main() {
    	ch := make(chan int, 2)
    	quit := make(chan int)
    	go put_chan(ch, 10)
    	go read_chan(ch, quit)
    
    
    	fmt.Println("end", <- quit, time.Now().UTC())
    
    }
    
    //// 例2、读阻塞等待
    //func put_chan(ch chan int, n int)  {
    //	for i := 0 ; i < n;  i++{
    //		time.Sleep(time.Duration(time.Second * 3))
    //		ch <- i
    //	}
    //	time.Sleep(time.Duration(time.Second * 3))
    //	close(ch)
    //}
    //
    //func read_chan(ch chan int, quit chan int)  {
    //	for c := range ch{
    //		fmt.Println(c, time.Now())
    //	}
    //	quit <- 1
    //}
    //func main() {
    //	ch := make(chan int, 2)
    //	quit := make(chan int)
    //	go put_chan(ch, 2)
    //	go read_chan(ch, quit)
    //
    //
    //	fmt.Println("end", <- quit, time.Now())
    //
    //}
    
    // 例3、测试中发现,系统检测会出现死锁
    //func main() {
    //	ch := make(chan int, 2)
    //	ch <- 1
    //	ch <- 2
    //	fmt.Println(<-ch)
    //	fmt.Println(<-ch)
    //  fmt.Println(<-ch)
    //	fmt.Println("end")
    //
    //}
    
    

    ex4

    /*
    Channels Range & Close 范围排列与关闭
    发送者可以通过关闭通道来通知没有更多数据需要发送了。
    接收者可以检测通道是否已经关闭了,通过指定第二个参数来实现,具体如下
    v , ok := <- ch
    当ok为false, 则通道已经关闭,没有数据了。
    或者可以使用循环 for i := range c 来取数据,至到通道关闭。
    注意<惯例>:
       1. 应该只让发送者来关闭通道。 绝对不要让接收者来关闭。 在一个已经关闭了的通道上发数据会引发panic
       2. 通道,只在最终不要了, 需要终止的时候才来关闭之
    */
    
    package main
    
    import (
    	"fmt"
    )
    
    func fibonacci(n int, c chan int) {
    	x, y := 0, 1
    	for i := 0; i < n; i++ {
    		c <- x
    		x, y = y, x+y
    	}
    	close(c)
    }
    
    func main() {
    	c := make(chan int, 10)
    	go fibonacci(cap(c), c)
    	for i := range c {
    		fmt.Println(i)
    	}
    }
    
    

    ex5

    /*
    Channels  select  选择查询操作
    选择查询语句, 让当前goroutine 等待多个通讯操作
    当没有条件满足时, select阻塞
    当有  条件满足时, select执行
    当有多条件满足时, select随机执行满足条件之一
    */
    
    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)
    }
    

    ex6

    /*
    Channels  select  选择查询操作
    缺省选择, 当没有case条件满足时, 直接选择默认条件
    */
    
    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	tick := time.Tick(100 * time.Millisecond)
    	boom := time.After(500 * time.Millisecond)
    	for {
    		select {
    		case <-tick:
    			fmt.Println("tick.")
    		case <-boom:
    			fmt.Println("BOOM!")
    			return
    		default:
    			fmt.Println("    .")
    			time.Sleep(50 * time.Millisecond)
    		}
    	}
    }
    
  • 相关阅读:
    Date Picker和UITool Bar控件简单介绍
    iOS开发UI篇—程序启动原理和UIApplication
    JS 随机生成随机数 数组
    你必须知道的28个HTML5特征、窍门和技术
    Javascript图片预加载详解
    弹性盒模型
    利用JSON.parse() 与 JSON.stringify() 实现深拷贝
    有关android及ios手机 中 input 调出数字键盘
    移动端 去除鼠标点击时的外轮廓
    H5 项目常见问题汇总及解决方案
  • 原文地址:https://www.cnblogs.com/freebird92/p/10518422.html
Copyright © 2020-2023  润新知