zoukankan      html  css  js  c++  java
  • golang channel 总结

    1、未初始化的channel读,阻塞

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	var ch chan int
    	go check(ch)
    
    	fmt.Println("main runtime end")
    	time.Sleep(time.Second * 1000)
    }
    
    func check(ch chan int) {
    	select {
    	case i := <-ch:
    		fmt.Println("read ch data=", i)
    	}
    	fmt.Println("check runtime exit")
    }
    
    

    2、未初始化的channel写,阻塞

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	go func() {
    		for {
    			time.Sleep(time.Second * 1)
    		}
    	}()
    	var ch chan int
    	go check(ch)
    	time.Sleep(time.Second * 1)
    	fmt.Println("xxxxxxx")
    	<-ch
    	fmt.Println("main runtime end")
    	time.Sleep(time.Second * 1000)
    }
    
    func check(ch chan int) {
    	defer func() {
    		if r := recover(); r != nil {
    			fmt.Println("recover ", r)
    		}
    	}()
    	ch <- 1
    	fmt.Println("check runtime exit")
    }
    
    

    3、向已关闭的channel读,返回默认值和false

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	var ch chan int
    	ch = make(chan int)
    	go check(ch)
    
    	fmt.Println("main runtime end")
    	close(ch)
    	time.Sleep(time.Second * 1000)
    }
    
    func check(ch chan int) {
    	select {
    	case i, k := <-ch:
    		fmt.Println("read ch data=", i, " k=", k) //k=false i=0
    	}
    	fmt.Println("check runtime exit")
    }
    
    

    4、向已关闭的channel写,panic

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	var ch chan int
    	ch = make(chan int)
    	close(ch)
    	ch <- 1
    	fmt.Println("end")
    	time.Sleep(time.Second * 1000)
    }
    
    

    5、time.Timer Stop后,time.Timer.C将阻塞

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	tm := time.NewTimer(time.Second * 3)
    	go check(tm)
    	time.Sleep(time.Second * 1)
    	tm.Stop()
    	fmt.Println("main runtime end")
    	time.Sleep(time.Second * 1000)
    }
    
    func check(tm *time.Timer) {
    	select {
    	case i, k := <-tm.C: //阻塞
    		fmt.Println("read ch data=", i, " k=", k)
    	}
    	fmt.Println("check runtime exit")
    }
    
    

    6、无缓冲与有缓冲channel的重要区别,无缓冲的channel在写时必须有读携程,否则会阻塞。如下例子,超时后向exit发数据会阻塞,因为只有一个携程,此时没有其他携程对exit进行读。【踩了坑才理解深刻】

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	exit := make(chan int)
    	go check(exit)
    	time.Sleep(time.Second * 100)
    }
    
    func check(exit chan int) {
    	tm := time.NewTimer(time.Second * 3)
    	select {
    	case <-exit:
    		fmt.Println("exit")
    	case <-tm.C:
    		fmt.Println("time out")
    		exit <- 1
    		fmt.Println("exit <- 1 ok")
    	}
    	fmt.Println("check runtime exit")
    }
    
    

    例子2:

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	go func() {
    		for {
    			time.Sleep(time.Second * 1)
    		}
    
    	}()
    	exit := make(chan int, 1)
    	exit <- 1
    	fmt.Println("end")
    }
    
    

    这里会直接END,如果exit:=make(chan int),会阻塞在exit<-1

  • 相关阅读:
    将Excel文件.xls导入SQL Server 2005
    linux mount命令
    python write file
    vim visual模式 复制
    chef简介
    录音整理文字工具otranscribe简介
    ftp put get 的使用方法
    yum lock 解决方法
    phalcon builder get raw sql
    centos7安装VirtualBox
  • 原文地址:https://www.cnblogs.com/cqvoip/p/8078910.html
Copyright © 2011-2022 走看看