GoLang 并发Goroutine&Channel(二)

GoLang 并发Goroutine&Channel(二)

1.channel通道初识

  • 通道是引用类型传递
func main() {
	var ch1 chan bool
	ch1 = make(chan bool)
	go func() {
		for i := 0; i < 10; i++ {
			time.Sleep(time.Second)
			fmt.Println(i)
		}
		fmt.Println("结束...")
		ch1 <- true
	}()
	fmt.Println("channel之前...")
	//阻塞在这里
	data := <-ch1
	fmt.Println(data)
	fmt.Println("main over...")
}
  • 发送和接收都是阻塞的
func main() {
	ch := make(chan int)
	go func() {
		fmt.Println("子goroutine执行...")
		time.Sleep(time.Second * 3)
		data := <-ch
		fmt.Println("data:", data)
	}()
	ch <- 200
	fmt.Println("main over...")
}

在这里插入图片描述

2.关闭通道和通道上的范围循环

(一)for循环的方式

func main() {
	ch1 := make(chan int)

	go SendData(ch1)

	for {
		time.Sleep(time.Second)
		v, ok := <-ch1
		if !ok {
			fmt.Println("结束...")
			break
		}
		fmt.Println(v)
	}
	fmt.Println("main over...")
}

func SendData(ch chan int) {
	defer close(ch)
	for i := 0; i < 10; i++ {
		ch <- i
	}
}

(二)for range的方式

func main() {
	ch := make(chan int)
	go SendData2(ch)
	for v := range ch {
		fmt.Println(v)
	}
	fmt.Println("main over...")
}

func SendData2(ch chan int) {
	defer close(ch)
	for i := 0; i < 10; i++ {
		time.Sleep(time.Second)
		ch <- i
	}
}

3.缓存通道

  • 相较于非缓冲通道,缓冲通道可以设置容量大小,只有达到容量的大小,读取和发送才会阻塞
func main() {
	ch := make(chan int, 4)
	go SendData3(ch)

	for v := range ch {
		fmt.Println("\t读取的数据:", v)
	}
	fmt.Println("main over...")
}

func SendData3(ch chan int) {
	defer close(ch)
	for i := 0; i < 10; i++ {
		ch <- i
		fmt.Println("发送的数据:", i)
	}
}

在这里插入图片描述

4.单向通道

  • 默认创建的通道都是双向通道
func main() {
	ch1 := make(chan string)
	done := make(chan bool)
	go sendData(ch1, done)
	data := <-ch1
	fmt.Println(data)
	ch1 <- "我是main goroutine..."
	<-done
}

func sendData(ch chan string, done chan bool) {
	ch <- "我是func goroutine..."
	data := <-ch
	fmt.Println(data)
	done <- true
}
  • 创建单项的通道(读,写)
  • 单项通道一般作为函数的形参使用,传入的实参还是用双向通道
func main() {
	ch1 := make(chan int) //双向通道
	//ch2 := make(chan<- int) //可写通道
	//ch3 := make(<-chan int) //可读通道

	//ch2 <- 100
	//data := <-ch2错误的写法

	//data := <-ch3
	//ch3 <- 100错误的写法

	//单项通道一般作为函数的形参使用,传入的实参还是用双向通道
	go fun1(ch1)

	data := <-ch1
	fmt.Println(data)

	go fun2(ch1)
	ch1 <- 999

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

func fun1(ch chan<- int) {
	ch <- 100
	fmt.Println("func1结束")
}

func fun2(ch <-chan int) {
	data := <-ch
	fmt.Println(data)
	fmt.Println("func2结束")
}

5.time包中的通道函数

func main() {
	timer := time.NewTimer(3 * time.Second)
	ch := timer.C
	fmt.Println(time.Now())
	fmt.Println(<-ch)
}
func main() {
	timer := time.NewTimer(5 * time.Second)
	go func() {
		<-timer.C
		fmt.Println("完成...")
	}()
	time.Sleep(3 * time.Second)
	timer.Stop()
	fmt.Println("main over...")
}
func main() {
	ch := time.After(3 * time.Second)
	fmt.Println(time.Now())
	fmt.Println(<-ch)
}

6.select语句

  • 如果没有default语句等待通信(阻塞),否则直接执行default语句
func main() {
	ch1 := make(chan int)
	ch2 := make(chan int)

	go func() {
		time.Sleep(3 * time.Second)
		ch1 <- 100
	}()

	go func() {
		ch2 <- 200
	}()

	select {
	case <-ch1:
		fmt.Println("case1 中的语句...")
	case <-ch2:
		fmt.Println("case2 中的语句...")
		/*default:
		fmt.Println("default...")*/
	}

	fmt.Println("main over...")
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值