zoukankan      html  css  js  c++  java
  • golang学习笔记之channel

    1.声明与初始化

    func main() {
    	// 声明 var 变量名 chan 数据类型
    	var c chan int
    
    	fmt.Printf("chan c : %v
    ", c)
    
    	// 初始化 make(chan 数据类型 [, int])
    	c = make(chan int)
    	fmt.Printf("chan c : %v
    ", c)
    	time.Sleep(time.Second * 5)
    
    	// 也可以这样声明和初始化
    	//ch := make(chan string, 2)
    	//ch <- "hello"
    	//ch <- "world"
    	//s1 := <-ch
    	//s2 := <-ch
    	//fmt.Println(s1, s2)
    }
    

      

      

    2.入队 出队

    var a chan int

    入队:  a <- 100

    出队: data := <- a

    3.无缓冲区channel

    初始化make时不指定容量.即: 

    func main() {
    	// 声明 var 变量名 chan 数据类型
    	var c chan int
    
    	fmt.Printf("chan c : %v
    ", c)
    
    	// 初始化一个无缓冲区channel
    	c = make(chan int)
    	fmt.Printf("chan c : %v
    ", c)
    	time.Sleep(time.Second * 5)
    }
    

      

    无缓冲区channel只有在读取的时候才能写入值

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func produce(c chan int) {
    	c <- 1000
    }
    
    func consume(c chan int) {
    	data := <-c
    	fmt.Printf("data : %v
    ", data)
    }
    
    func main() {
    	// 声明 var 变量名 chan 数据类型
    	var c chan int
    
    	fmt.Printf("chan c : %v
    ", c)
    
    	// 初始化无缓冲区channel
    	c = make(chan int)
    
    	// 写入channel
    	go produce(c)
    
    	// 消费(读取)channel
    	go consume(c)
    
    	time.Sleep(time.Second * 5)
    }
    

      

    如果注释掉 go consume(c), 那么将没有消费(读取)channel,程序就会一直阻塞直到主线程结束.(如下节:阻塞channel)

    当有go consume(c)进行消费(读取)时,才能写入并读取出channel的值

    4.阻塞channel

    func main() {
    	var a chan int
    	if a == nil {
    		fmt.Println("channel is nil, going to define it")
    		a = make(chan int)
    		a <- 10 //将一直阻塞在这里
    		fmt.Printf("Type of a is : %T", a)
    	}
    }
    

      

    带缓冲区与不带缓冲区 区别举例:

    1.不带缓冲区:面对面签收快递.无收件人取件时(读取),快递员死等(阻塞,除非主线程结束,如下班)

    2.带缓冲区:快递员将包裹存放在柜中(如蜂巢,柜子的数量就是缓冲的容量)

    5.使用channel对goroutine进行同步  

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func hello(c chan bool) {
    	time.Sleep(time.Second * 5)
    	fmt.Println("只有当我执行后,主线程才能退出哦!")
    	c <- true
    }
    
    func main() {
    	var exitChan chan bool
    	exitChan = make(chan bool)
    	go hello(exitChan)
    	// 只有当子线程中的 channel写入值之后,下面才能读取.否则将一直阻塞
    	<-exitChan
    	fmt.Println("主线程结束")
    }
    

    6.单向channel

    var a chan<- int //只写

    var b <-chan int //只读

    7.关闭channel

    close(c)

    8.判断关闭及遍历channel数据

    a.使用ok判断并使用for循环遍历channel

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func hello(c chan bool) {
    	time.Sleep(time.Second * 5)
    	fmt.Println("只有当我执行后,主线程才能退出哦!")
    	c <- true
    }
    
    func main() {
    	var exitChan chan bool
    	exitChan = make(chan bool)
    	go hello(exitChan)
    	// 只有当子线程中的 channel写入值之后,下面才能读取.否则将一直阻塞
    	<-exitChan
    	fmt.Println("主线程结束")
    }
    

      

    b.使用 for range遍历-----推荐方式(自动判断是否关闭)

    package main
    
    import "fmt"
    
    func produce(c chan int) {
    	for i := 0; i < 10; i++ {
    		c <- i
    	}
    	close(c)
    }
    
    func main() {
    	ch := make(chan int)
    	go produce(ch)
    
    	// 使用for range 对channel数据遍历
    	for v := range ch {
    		fmt.Println("接收数据: ", v)
    	}
    }
    

      

    9.带缓冲区channel

    package main
    
    import "fmt"
    
    func main() {
    	var ch chan string
    	ch = make(chan string, 3)
    
    	ch <- "hello"
    	ch <- "world"
    	ch <- "!"
    
    	//先入先出
    	s1 := <-ch
    	s2 := <-ch
    	s3 := <-ch
    	fmt.Println(s1, s2, s3)
    }
    

    注:channel空或者满 都会阻塞

    10.使用waitgroup等待一组goroutine结束(sync.WaitGroup)

    原理:计数.  1.起一个goruntine时计数加一 2.执行完一个gorutine时计数减一 3.当计数为0时结束 

    package main
    
    import (
    	"fmt"
    	"sync"
    	"time"
    )
    
    func process(i int, wg *sync.WaitGroup) {
    	fmt.Println("started gorutine ", i)
    	time.Sleep(time.Second * 2)
    	fmt.Printf("goruntine %d ended 
    ", i)
    	wg.Done() //执行完waitgroup计数减一
    }
    
    func main() {
    	// 场景: 需要一组gorutine都执行完 才退出
    	var wg sync.WaitGroup
    	no := 10
    	for i := 0; i < no; i++ {
    		wg.Add(1) //起一个gorutine时 计数加一
    		go process(i, &wg)
    	}
    	wg.Wait() //当计数为0时 等待结束
    	fmt.Println("All go runtines finished executing")
    }
    

      

  • 相关阅读:
    jython resources
    Installing a Library of Jython ScriptsPart of the WebSphere Application Server v7.x Administration Series Series
    jython好资料
    ulipad install on 64bit win7 has issue
    an oracle article in high level to descibe how to archtichre operator JAVA relevet project
    table的宽度,单元格内换行问题
    Linux常用命令大全
    dedecms系统后台登陆提示用户名密码不存在
    登录织梦后台提示用户名不存在的解决方法介绍
    Shell常用命令整理
  • 原文地址:https://www.cnblogs.com/yin5th/p/9201406.html
Copyright © 2011-2022 走看看