Go语言进阶第04天(通道同步异步与周期)

1.channel同步-传递数据

package main

import "fmt"

func main01() {
    
    
	ch := make(chan string) // 无缓冲channel
	// len(ch) : channel 中剩余未读取数据个数。 cap(ch): 通道的容量。
	fmt.Println("len(ch)=", len(ch), "cap(ch)=", cap(ch))
	go func() {
    
    
		for i := 0; i < 2; i++ {
    
    
			fmt.Println("i = ", i, "len(ch)=", len(ch), "cap(ch)=", cap(ch))
		}
		// 通知主go打印完毕
		ch <- "子go打印完毕"
		fmt.Println("len(ch)=", len(ch), "cap(ch)=", cap(ch))

	}()

	str := <-ch
	fmt.Println("len(ch)=", len(ch), "cap(ch)=", cap(ch))

	fmt.Println("str=", str)
}

2.无缓冲的channel

package main

import (
	"fmt"
)

func main02() {
    
    
	ch := make(chan int)

	go func() {
    
    
		for i := 0; i < 5; i++ {
    
    
			fmt.Println("子go程, i=", i)
			ch <- i // ch <- 0
		}
	}()
	//time.Sleep(time.Second * 2)
	for i := 0; i < 5; i++ {
    
    
		num := <-ch
		fmt.Println("主go程读:", num)
	}
}

3.有缓冲的channel

package main

import (
	"fmt"
)

func main03() {
    
    
	ch := make(chan int, 5) // 存满3个元素之前,不会阻塞
	fmt.Println("len=", len(ch), "cap=", cap(ch))

	go func() {
    
    
		for i := 0; i < 10; i++ {
    
    
			ch <- i
			len := len(ch)
			cap := cap(ch)
			fmt.Println("子go程:i", i, "len=", len, "cap=", cap)
			//fmt.Println("子go程:i", i)
		}
	}()
	//time.Sleep(time.Second * 3)
	for i := 0; i < 8; i++ {
    
    
		num := <-ch
		fmt.Println("主go程读到:", num)
	}
}

4.关闭channel

package main

import (
	"fmt"
	"time"
)

/*func main()  {
	ch := make(chan int)

	go func() {
		for i:=0; i<8;i++ {
			ch <- i
		}
		close(ch)		// 写端,写完数据主动关闭channel
		//ch <- 790
	}()

	for {
		if num, ok := <- ch; ok == true {
			fmt.Println("读到数据:", num)
		} else {
			n := <- ch
			fmt.Println("关闭后:", n)
			break
		}
	}
}*/

func main04() {
    
    
	ch := make(chan int, 0)

	go func() {
    
    
		for i := 0; i < 5; i++ {
    
    
			ch <- i
		}
		close(ch) // 写端,写完数据主动关闭channel
		//ch <- 790
		fmt.Println("子go 结束")
	}()
	time.Sleep(time.Second * 2)
	/*	for {
		if num, ok := <- ch; ok == true {
			fmt.Println("读到数据:", num)
		} else {
			n := <- ch
			fmt.Println("关闭后:", n)
			break
		}
	}*/
	for num := range ch {
    
    
		fmt.Println("读到数据:", num)
	}
}

5.单向channel

package main

import "fmt"

/*func main()  {
	ch := make(chan int) 			// 双向channel

	var sendCh chan <- int = ch
	sendCh <- 789
	//num := <- sendCh

	var recvCh <- chan int = ch
	num := <-recvCh
	fmt.Println("num=", num)

	// 反向赋值
	//var ch2 chan int = recvCh
}*/

func send(out chan<- int) {
    
    
	out <- 89
	close(out)
}

func recv(in <-chan int) {
    
    
	n := <-in
	fmt.Println("读到", n)
}

func main0500() {
    
    
	ch := make(chan int) // 双向channel
	go func() {
    
    
		send(ch) // 双向channel 转为 写channel
	}()
	recv(ch)
}

6.生产者消费者模型

package main

import (
	"fmt"
	"time"
)

func producer(out chan<- int) {
    
    
	for i := 0; i < 10; i++ {
    
    
		fmt.Println("生产:", i*i)
		out <- i * i
	}
	close(out)
}

func consumer(in <-chan int) {
    
    
	for num := range in {
    
    
		fmt.Println("消费者拿到:", num)
		time.Sleep(time.Second)
	}
}

func main06() {
    
    
	ch := make(chan int, 6)
	go producer(ch) // 子go程 生产者
	consumer(ch)    // 主go程 消费
}

7.定时器

package main

import (
	"fmt"
	"time"
)

func main0701() {
    
    
	fmt.Println("当前时间:", time.Now())
	// 创建定时器
	myTimer := time.NewTimer(time.Second * 2)
	nowTime := <-myTimer.C // chan 类型
	fmt.Println("现下时间:", nowTime)
}

// 3 种定时方法
func main0702() {
    
    
	// 1 . sleep
	time.Sleep(time.Second)

	// 2. Timer.C
	myTimer := time.NewTimer(time.Second * 2) // 创建定时器, 指定定时时长
	nowTime := <-myTimer.C                    // 定时满,系统自动写入系统时间
	fmt.Println("现下时间:", nowTime)

	// 3 time.After
	fmt.Println("当前时间:", time.Now())
	nowTime2 := <-time.After(time.Second * 2)
	fmt.Println("现下时间:", nowTime2)
}

// 定时器的停止和重置
func main07() {
    
    

	myTimer := time.NewTimer(time.Second * 10) // 创建定时器。
	myTimer.Reset(1 * time.Second)             // 重置定时时长为 1
	go func() {
    
    
		for {
    
    
			<-myTimer.C
			fmt.Println("子go程,定时完毕")
		}
	}()

	//myTimer.Stop()		// 设置定时器停止
	for {
    
    

	}
}

8.周期定时

package main

import (
	"fmt"
	"time"
)

func main08() {
    
    

	quit := make(chan bool) // 创建一个判断是否 终止的channel

	fmt.Println("now:    ", time.Now())
	myTicker := time.NewTicker(time.Second) // 定义一个周期定时器

	i := 0
	go func() {
    
    
		for {
    
    
			nowTime := <-myTicker.C
			i++
			fmt.Println("nowTime:", nowTime)
			if i == 3 {
    
    
				quit <- true // 解除 主go程阻塞。
				break        // return // runtime.Goexit
			}
		}
	}()

	<-quit // 子go程 循环获取 <-myTicker.C 期间,一直阻塞
}

9.select监听通道数据流

package main

import (
	"fmt"
	"runtime"
	"time"
)

func main09() {
    
    
	ch := make(chan int)    // 用来进行数据通信的 channel
	quit := make(chan bool) // 用来判断是否退出的 channel
	//ch2 := make(chan string)
	go func() {
    
     // 写数据
		for i := 0; i < 5; i++ {
    
    
			ch <- i
			time.Sleep(time.Second)
		}
		close(ch)
		quit <- true // 通知主go程 退出
		runtime.Goexit()
	}()
	for {
    
     // 主go程 select 监听 chan数据流动
		select {
    
    
		case num := <-ch: // 不可读,阻塞。可以读,将数据保存至num
			fmt.Println("读到:", num) // 模拟使用数据

		case <-quit: // 不可读,阻塞。可以读,将主go程结束。
			//break // break 跳出 select	不可用
			//runtime.Goexit()	// 终止 主 go 程		不可用
			return // 终止进程
		}
		fmt.Println("============") // select 自身不带有循环机制,需借助外层 for 来循环监听
	}
}

10.select实现斐波那数列

package main

import (
	"fmt"
	"runtime"
)

func fibonacci(ch <-chan int, quit <-chan bool) {
    
    
	for {
    
    
		select {
    
    
		case num := <-ch:
			fmt.Print(num, " ")
		case <-quit:
			//return
			runtime.Goexit() //等效于 return
		}
	}
}

func main() {
    
    
	ch := make(chan int)
	quit := make(chan bool)

	go fibonacci(ch, quit) // 子go 程 打印fibonacci数列

	x, y := 1, 1
	for i := 0; i < 40; i++ {
    
    
		ch <- x
		x, y = y, x+y
	}
	quit <- true
}

猜你喜欢

转载自blog.csdn.net/qq_51685718/article/details/127702349