package mainimport ("fmt""time")// 在主线程(可以理解成进程)中,开启一个goroutine, 该协程每隔50毫秒秒输出 "你好golang"// 在主线程中也每隔50毫输出"你好golang", 输出10次后,退出程序// 要求主线程和goroutine同时执行func test() {for i := 0; i < 10; i++ {fmt.Println("test() 你好golang")time.Sleep(time.Millisecond * 100)}}func main() {go test() //表示开启一个协程for i := 0; i < 10; i++ {fmt.Println("main() 你好golang")time.Sleep(time.Millisecond * 100)}}
package mainimport ("fmt""sync""time")//主线程退出后所有的协程无论有没有执行完毕都会退出,所以我们在主进程中可以通过WaitGroup等待协程执行完毕var wg sync.WaitGroupfunc test1() {for i := 0; i < 10; i++ {fmt.Println("test1() 你好golang-", i)time.Sleep(time.Millisecond * 100)}wg.Done() //协程计数器-1}func test2() {for i := 0; i < 10; i++ {fmt.Println("test2() 你好golang-", i)time.Sleep(time.Millisecond * 100)}wg.Done() //协程计数器-1}func main() {wg.Add(1) //协程计数器+1go test1() //表示开启一个协程wg.Add(1) //协程计数器+1go test2() //表示开启一个协程wg.Wait() //等待协程执行完毕...fmt.Println("主线程退出...")}
package mainimport ("fmt""runtime")func main() {//获取当前计算机上面的Cup个数cpuNum := runtime.NumCPU()fmt.Println("cpuNum=", cpuNum)//可以自己设置使用多个cpuruntime.GOMAXPROCS(cpuNum - 1)fmt.Println("ok")}
package mainimport ("fmt""sync""time")//多携程的一个案例var wg sync.WaitGroupfunc test(num int) {defer wg.Done()for i := 1; i <= 5; i++ {fmt.Printf("协程(%v)打印的第%v条数据\n", num, i)time.Sleep(time.Millisecond * 100)}}func main() {for i := 1; i <= 6; i++ {wg.Add(1)go test(i)}wg.Wait()fmt.Println("关闭主线程...")}
package mainimport ("fmt""time")//需求:要统计1-120000的数字中那些是素数?for循环实现func main() {start := time.Now().Unix()for num := 2; num < 120000; num++ {var flag = truefor i := 2; i < num; i++ {if num%i == 0 {flag = falsebreak}}if flag {// fmt.Println(num, "是素数")}}end := time.Now().Unix()fmt.Println(end - start) //11毫秒 11毫秒}
package mainimport ("fmt""sync""time")//需求:要统计1-120000的数字中那些是素数?goroutine for循环实现/*1 协程 统计 1-300002 协程 统计 30001-600003 协程 统计 60001-900004 协程 统计 90001-120000// start:(n-1)*30000+1 end:n*30000*/var wg sync.WaitGroupfunc test(n int) {for num := (n-1)*30000 + 1; num < n*30000; num++ {if num > 1 {var flag = truefor i := 2; i < num; i++ {if num%i == 0 {flag = falsebreak}}if flag {// fmt.Println(num, "是素数")}}}wg.Done()}func main() {start := time.Now().Unix()for i := 1; i <= 4; i++ {wg.Add(1)go test(i)}wg.Wait()fmt.Println("执行完毕")end := time.Now().Unix()fmt.Println(end - start) //4毫秒}
package mainimport "fmt"func main() {//1、创建channelch := make(chan int, 3)//2、给管道里面存储数据ch <- 10ch <- 21ch <- 32//3、获取管道里面的内容a := <-chfmt.Println(a) //10<-ch //从管道里面取值 //21c := <-chfmt.Println(c) //32ch <- 56ch <- 66//4、打印管道的长度和容量fmt.Printf("值:%v 容量:%v 长度%v\n", ch, cap(ch), len(ch)) //值:0xc0000d0080 容量:3 长度2// 5、管道的类型(引用数据类型)ch1 := make(chan int, 4)ch1 <- 34ch1 <- 54ch1 <- 64ch2 := ch1ch2 <- 69<-ch1<-ch1<-ch1d := <-ch1fmt.Println(d) //69//8、管道阻塞// ch6 := make(chan int, 1)// ch6 <- 34// ch6 <- 64 //all goroutines are asleep - deadlock!// 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告 deadlock// ch7 := make(chan string, 2)// ch7 <- "数据1"// ch7 <- "数据2"// m1 := <-ch7// m2 := <-ch7// m3 := <-ch7// fmt.Println(m1, m2, m3) //fatal error: all goroutines are asleep - deadlock!//正确的写法ch8 := make(chan int, 1)ch8 <- 34<-ch8ch8 <- 67<-ch8ch8 <- 78m4 := <-ch8fmt.Println(m4)}
package mainimport "fmt"// 循环遍历管道数据func main() {//2、使用for range遍历通道,当通道被关闭的时候就会退出for range,如果没有关闭管道就会报个错误fatal error: all goroutines are asleep - deadlock!// var ch1 = make(chan int, 10)// for i := 1; i <= 10; i++ {// ch1 <- i// }// close(ch1) //关闭管道// //for range循环遍历管道的值 ,注意:管道没有key// for v := range ch1 {// fmt.Println(v)// }//2、通过for循环遍历管道的时候管道可以不关闭var ch2 = make(chan int, 10)for i := 1; i <= 10; i++ {ch2 <- i}for j := 0; j < 10; j++ {fmt.Println(<-ch2)}}
package mainimport ("fmt""sync")package mainvar wg sync.WaitGroupfunc putNum(intChan chan int) {for i := 2; i < 10; i++ {intChan <- ifmt.Println(i)}close(intChan)wg.Done()}//定义一个存放任意数据类型的管道 3个数据func main() {// allChan := make(chan interface{}, 3)// allChan <- 10// allChan <- "tom jack"// cat := Cat{"小花猫", 4}// allChan <- cat// //我们希望获得到管道中的第三个元素,则先将前2个推出// <-allChan// <-allChan// newCat := <-allChan //从管道中取出的Cat是什么?// fmt.Printf("newCat=%T , newCat=%v\n", newCat, newCat)// //下面的写法是错误的!编译不通过// //fmt.Printf("newCat.Name=%v", newCat.Name)// //使用类型断言// a := newCat.(Cat)// fmt.Printf("newCat.Name=%v", a.Name)var intChan = make(chan int, 1000)wg.Add(1)go putNum()wg.Wait()()}
package mainimport ("fmt""sync""time")/*需求:使用goroutine和channel协同工作案例1、开启一个WriteData的的协程给向管道inChan中写入100条数据2、开启一个ReadData的协程读取inChan中写入的数据3、注意:WriteData和ReadData同时操作一个管道4、主线程必须等待操作完成后才可以退出goroutine结合Channel使用的简单demo,定义两个方法,一个方法给管道里面写数据,一个给管道里面读取数据。要求同步进行。*/var wg sync.WaitGroup//写数据func fn1(ch chan int) {for i := 1; i <= 10; i++ {ch <- ifmt.Printf("【写入】数据%v成功\n", i)time.Sleep(time.Millisecond * 5000)}close(ch)wg.Done()}func fn2(ch chan int) {for v := range ch {fmt.Printf("【读取】数据%v成功\n", v)time.Sleep(time.Millisecond * 10)}wg.Done()}func main() {var ch = make(chan int, 10)wg.Add(1)go fn1(ch)wg.Add(1)go fn2(ch)wg.Wait()fmt.Println("退出...")}
package mainimport ("fmt""sync""time")var wg sync.WaitGroupfunc main() {// 1、创建channelvar ch1 = make(chan int, 3)wg.Add(1)go func() {for i := 1; i <= 3; i++ {num := <-ch1fmt.Println(num)}wg.Done()}()wg.Add(1)go func() {for i := 1; i <= 3; i++ {time.Sleep(time.Second)ch1 <- i}wg.Done()}()wg.Wait()}
package mainimport ("fmt""sync""time")var wg sync.WaitGroup//向 intChan放入 1-120000个数func putNum(intChan chan int) {for i := 2; i < 120000; i++ {intChan <- i}close(intChan)wg.Done()}// 从 intChan取出数据,并判断是否为素数,如果是,就把得到的素数放在primeChanfunc primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {for num := range intChan {var flag = truefor i := 2; i < num; i++ {if num%i == 0 {flag = falsebreak}}if flag {primeChan <- num //num是素数}}//要关闭 primeChan// close(primeChan) //如果一个channel关闭了就没法给这个channel发送数据了//什么时候关闭primeChan?//给exitChan里面放入一条数据exitChan <- truewg.Done()}//printPrime打印素数的方法func printPrime(primeChan chan int) {// for v := range primeChan {// fmt.Println(v)// }wg.Done()}func main() {start := time.Now().Unix()intChan := make(chan int, 1000)primeChan := make(chan int, 50000)exitChan := make(chan bool, 16) //标识primeChan close//存放数字的协程wg.Add(1)go putNum(intChan)//统计素数的协程for i := 0; i < 16; i++ {wg.Add(1)go primeNum(intChan, primeChan, exitChan)}//打印素数的协程wg.Add(1)go printPrime(primeChan)//判断exitChan是否存满值wg.Add(1)go func() {for i := 0; i < 16; i++ {<-exitChan}//关闭primeChanclose(primeChan)wg.Done()}()wg.Wait()end := time.Now().Unix()fmt.Println("执行完毕....", end-start, "毫秒")}
package mainimport "fmt"//单向管道func main() {// 1、在默认情况下下,管道是双向ch1 := make(chan int, 2)ch1 <- 10ch1 <- 12m1 := <-ch1m2 := <-ch1fmt.Println(m1, m2) //10 12// 2、管道声明为只写ch2 := make(chan<- int, 2)ch2 <- 10ch2 <- 12// <-ch2 //receive from send-only type chan<- int// 3、管道声明为只读ch3 := make(<-chan int, 2)// ch3 <- 23}
package mainimport ("fmt""sync""time")/*需求:使用goroutine和channel协同工作案例1、开启一个WriteData的的协程给向管道inChan中写入100条数据2、开启一个ReadData的协程读取inChan中写入的数据3、注意:WriteData和ReadData同时操作一个管道4、主线程必须等待操作完成后才可以退出goroutine结合Channel使用的简单demo,定义两个方法,一个方法给管道里面写数据,一个给管道里面读取数据。要求同步进行。*/var wg sync.WaitGroup//写数据func fn1(ch chan<- int) {for i := 1; i <= 10; i++ {ch <- ifmt.Printf("【写入】数据%v成功\n", i)time.Sleep(time.Millisecond * 50)}close(ch)wg.Done()}//读取管道里面的数据func fn2(ch <-chan int) {for v := range ch {fmt.Printf("【读取】数据%v成功\n", v)time.Sleep(time.Millisecond * 50)}wg.Done()}func main() {var ch = make(chan int, 10)wg.Add(1)go fn1(ch)wg.Add(1)go fn2(ch)wg.Wait()fmt.Println("退出...")}
package mainimport ("fmt""time")func main() {// 在某些场景下我们需要同时从多个通道接收数据,这个时候就可以用到golang中给我们提供的select多路复用//1.定义一个管道 10个数据intintChan := make(chan int, 10)for i := 0; i < 10; i++ {intChan <- i}//2.定义一个管道 5个数据stringstringChan := make(chan string, 5)for i := 0; i < 5; i++ {stringChan <- "hello" + fmt.Sprintf("%d", i)}//使用select来获取channel里面的数据的时候不需要关闭channelfor {select {case v := <-intChan:fmt.Printf("从 intChan 读取的数据%d\n", v)time.Sleep(time.Millisecond * 50)case v := <-stringChan:fmt.Printf("从 stringChan 读取的数据%v\n", v)time.Sleep(time.Millisecond * 50)default:fmt.Printf("数据获取完毕")return //注意退出...}}}
package mainimport ("fmt""time")//函数func sayHello() {for i := 0; i < 10; i++ {time.Sleep(time.Millisecond * 50)fmt.Println("hello,world")}}//函数func test() {//这里我们可以使用defer + recoverdefer func() {//捕获test抛出的panicif err := recover(); err != nil {fmt.Println("test() 发生错误", err)}}()//定义了一个mapvar myMap map[int]stringmyMap[0] = "golang" //error}func main() {go sayHello()go test()//防止主进程退出这里使用time.Sleep演示,搭建也可以用sync.WaitGrouptime.Sleep(time.Second)}
package main//go build -race main.go 编译后运行查看import ("fmt""sync""time")var count = 0var wg sync.WaitGroupvar mutex sync.Mutexfunc test() {mutex.Lock()count++fmt.Println("the count is : ", count)time.Sleep(time.Millisecond)mutex.Unlock()wg.Done()}func main() {for r := 0; r < 20; r++ {wg.Add(1)go test()}wg.Wait()}
package main//go build -race main.go 编译后运行查看import ("fmt""sync""time")var wg sync.WaitGroupvar mutex sync.Mutexvar m = make(map[int]int, 0)func test(num int) {mutex.Lock()var sum = 1for i := 1; i <= num; i++ {sum *= i}m[num] = sum// fmt.Println(m[num])fmt.Printf("key=%v value=%v\n", num, sum)time.Sleep(time.Millisecond)mutex.Unlock()wg.Done()}func main() {for r := 0; r < 40; r++ {wg.Add(1)go test(r)}wg.Wait()}
package mainimport ("fmt""sync""time")var wg sync.WaitGroupvar mutex sync.RWMutex//写的方法func write() {mutex.Lock()fmt.Println("执行写操作")time.Sleep(time.Second * 2)mutex.Unlock()wg.Done()}//读的方法func read() {mutex.RLock()fmt.Println("---执行读操作")time.Sleep(time.Second * 2)mutex.RUnlock()wg.Done()}func main() {//开启10个协程执行读操作for i := 0; i < 10; i++ {wg.Add(1)go write()}// 开启10个协程执行写操作for i := 0; i < 10; i++ {wg.Add(1)go read()}wg.Wait()}
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论