go的一些实现(关于channel循环打印,限流等等)

go如何实现深拷贝?

  • 序列化和反序列化
import (
	"bytes"
	"encoding/gob"
	"fmt"
)


func deepCopy(dst, src interface{}) error {
	var buf bytes.Buffer
	if err := gob.NewEncoder(&buf).Encode(src); err != nil {
		return err
	}
	return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst)
}

两个协程交替打印奇偶数

//两个协程交替打印奇偶数

func main(){
	flagChan:=make(chan struct{}) //无缓冲chan

	go func() {
		for i:=1;i<=10;i++{
			flagChan<- struct{}{}
			if i&1==1{
				fmt.Println("goroutine one:",i)
			}
		}
	}()


	go func() {
		for i:=1;i<=10;i++{
			<-flagChan
			if i&1==0{
				fmt.Println("gorroutine two:",i)
			}
		}
	}()

   time.Sleep(3*time.Second)
}

两个协程循环打印字母和数字

//两个协程轮流打印数字和字母  A 1 B 2 C 3 .... Z 26


func main(){
	Buffer() //有缓冲的方式
	NoBuffer() //无缓冲的方式
}


//有缓冲区的chan循环打印.

func Buffer(){
	strChan:=make(chan struct{},1)
	numChan:=make(chan struct{},1)

	//先向numChan中放入作为开启
	numChan<- struct{}{}

	go func(){
		for i:='A';i<='Z';i++{
			<-numChan //读取之后才能继续
			fmt.Printf("%v ",string(i))
			strChan<- struct{}{}
		}
	}()

	go func() {
		for i:=1;i<=26;i++{
			<-strChan
			fmt.Printf("%v ",i)
			numChan<- struct{}{} //通知数字打印完毕
		}
	}()

	time.Sleep(3*time.Second)
}



//无缓冲的chan实现方式
func NoBuffer(){
	//
	strChan:=make(chan struct{})
	numChan:=make(chan struct{})

	go func(){
		for i:='A';i<='Z';i++{
			fmt.Printf("%v ",string(i))
			strChan<- struct{}{}
			<-numChan //读取之后才能继续
		}
	}()

	go func() {
		for i:=1;i<=26;i++{
			<-strChan
			fmt.Printf("%v ",i)
			numChan<- struct{}{} //通知数字打印完毕
		}
	}()

	time.Sleep(3*time.Second)
}

N个协程循环打印1-100

//N个协程交替打印1-100
const NUM = 5  //假设5个协程交替打印

func main(){

	exitChan:=make(chan int,1) //退出的标识
	chanNums:=make([]chan int,0)  //chan数组 ,开启多个协程哪个对应的chan到达则可以运行
	res:=1 //全局res,因为交替打印,多协程操作也不需要加锁
	index:=0 //协程标识,到达NUM重新归零

	for i:=0;i<NUM;i++{  //初始化对应的chan
		chanNums = append(chanNums,make(chan int,1))
	}


	for i:=0;i<NUM;i++{
		go func(i int) { //开启NUM个协程
			for { //循环打印
				<-chanNums[i] //对应的chan存在数据才打印
				if res>100{ //越界退出
					exitChan<-1
					break
				}
				fmt.Println("goroutine",i, "res:",res)
				res++

				index = (index+1)%NUM  //5个协程index为0,1,2,3,4  到达4之后重新归零

				chanNums[index]<-1 //放入下一个
			}
		}(i)
	}

	//初始化时候先把第一个打印goroutine开启
	chanNums[0]<-1

	//退出标识存在才会退出
	select {
	case <-exitChan:
		fmt.Println("main终止")
	}
}

posted @ 2022-06-11 23:00  海拉尔  阅读(330)  评论(0编辑  收藏  举报