七叶笔记 » golang编程 » 关于go语言中的协程相关知识点总结(二)

关于go语言中的协程相关知识点总结(二)

关于Channel(通道)

通道是go提供的一种通信机制,允许协程间进行数据传输,通道是需要指定类型的,是需要使用chan关键字声明的,是可以用close()方法进行关闭通道 的

关于通道的写入与读取

注意看代码里的注释!!!!

 package main

import (
	"fmt"
	"time"
)

func writeToChan(c chan int,x int)  {
	fmt.Println("写之前",x)
	//向通道里写数据
	c<-x
    close(c)
	//下面的打印,会在读数据之后执行,如果不读,则一直阻塞了,等1s后,程序结束也不会打印了!
	fmt.Println("写之后",x)
}
func main() {
	c := make(chan int)
	//向通道里写值
	go writeToChan(c,10)
	time.Sleep(1*time.Second)
	//fmt.Println("读数据",<-c)
	time.Sleep(1*time.Second)
    v,ok:=<-c
    //可以通过ok判读通道是否关闭
    if ok{
        fmt.Println("通道开着呢")
    }else{
        fmt.Println("通道关闭了")
    }

}  

通道作为函数参数传递

在当函数参数时,可以指定通道是只读通道或者是只写通道

 //声明f1中能通道c只能是只写通道,并不能从当前通道里读取数据
func f1(c chan<- int,x int )  {

}
//声明f2中能通道c只能是只读通道,并不能从当前通道里写数据
func f2(c <-chan int,x int )  {

}  

来个比较综合点的例子

利用 channel(通道) 来模拟一下管道!!!

需求:计算所有随机数的和,如果随机数有重复的,则停止计算

 package main

import (
	"fmt"
	"math/rand"
	"os"
	"strconv"
	"time"
)
//定义一个标志位
var closea=false
var data=make(map[int]bool)
//随机数函数
func random(min,max int) int  {
	return rand.Intn(max-min)+min
}
//把随机数写入通道
func one(min,max int ,out chan<- int){
	for{
		//如果为真,则关闭通道
		if closea{
			close(out)
			return
		}
		//生成的随机数写入通道中
		out<-random(min,max)
	}
}
//从通道里取值,判断值在不在map中,如果不在加入新的通道中,如果在map中,则关闭one中的通道
func two(out chan<- int,in <-chan int)  {
	//从in通道里读取数据,并判断,如果有这个int值存在,则改变标志位,关闭out通道
	for x := range in {
		fmt.Println("x",x," ")
		//判断这个值在不在map中,如果在,则改标志位,如果不在,则添加到这个map中,并把这个值,发送到一个out通道中
		_,ok :=data[x]
		if ok{
			closea=true
		}else{
			data[x]=true
			out<-x
		}
	}
	fmt.Println()
	//写完数据关闭通道
	close(out)
}
//从通道里取数据,并计算结果
func three(in <-chan int)  {
	var sum int
	for  x2:= range in {
		sum=sum+x2
	}
	fmt.Println("随机数的和是",sum)

}
func main() {
	args :=os.Args
	if len(args)==1{
		fmt.Println("参数缺失")
		os.Exit(1)
	}
	n1,_:=strconv.Atoi(args[1])
	n2,_:=strconv.Atoi(args[2])
	if n1>n2{
		fmt.Println("最小值与最大值位置不对")
		return
	}
	rand.Seed(time.Now().Unix())
	//注意在声明的时候,不要声明带方向的通道,要不无法使用
	a :=make(chan int)
	b :=make(chan int)
	go one(n1,n2,a)
	go two(b,a)
    //最后这个不协程,主要是为了阻塞主函数完成
	three(b)
}  

相关文章