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) //协程计数器+1 go test1() //表示开启一个协程 wg.Add(1) //协程计数器+1 go test2() //表示开启一个协程 wg.Wait() //等待协程执行完毕... fmt.Println("主线程退出...")}
package mainimport ( "fmt" "runtime")func main() { //获取当前计算机上面的Cup个数 cpuNum := runtime.NumCPU() fmt.Println("cpuNum=", cpuNum) //可以自己设置使用多个cpu runtime.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 = true for i := 2; i < num; i++ { if num%i == 0 { flag = false break } } 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 = true for i := 2; i < num; i++ { if num%i == 0 { flag = false break } } 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、创建channel ch := make(chan int, 3) //2、给管道里面存储数据 ch <- 10 ch <- 21 ch <- 32 //3、获取管道里面的内容 a := <-ch fmt.Println(a) //10 <-ch //从管道里面取值 //21 c := <-ch fmt.Println(c) //32 ch <- 56 ch <- 66 //4、打印管道的长度和容量 fmt.Printf("值:%v 容量:%v 长度%v\n", ch, cap(ch), len(ch)) //值:0xc0000d0080 容量:3 长度2 // 5、管道的类型(引用数据类型) ch1 := make(chan int, 4) ch1 <- 34 ch1 <- 54 ch1 <- 64 ch2 := ch1 ch2 <- 69 <-ch1 <-ch1 <-ch1 d := <-ch1 fmt.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 <-ch8 ch8 <- 67 <-ch8 ch8 <- 78 m4 := <-ch8 fmt.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 <- i fmt.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 <- i fmt.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、创建channel var ch1 = make(chan int, 3) wg.Add(1) go func() { for i := 1; i <= 3; i++ { num := <-ch1 fmt.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 = true for i := 2; i < num; i++ { if num%i == 0 { flag = false break } } if flag { primeChan <- num //num是素数 } } //要关闭 primeChan // close(primeChan) //如果一个channel关闭了就没法给这个channel发送数据了 //什么时候关闭primeChan? //给exitChan里面放入一条数据 exitChan <- true wg.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 } //关闭primeChan close(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 <- 10 ch1 <- 12 m1 := <-ch1 m2 := <-ch1 fmt.Println(m1, m2) //10 12 // 2、管道声明为只写 ch2 := make(chan<- int, 2) ch2 <- 10 ch2 <- 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 <- i fmt.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个数据int intChan := make(chan int, 10) for i := 0; i < 10; i++ { intChan <- i } //2.定义一个管道 5个数据string stringChan := make(chan string, 5) for i := 0; i < 5; i++ { stringChan <- "hello" + fmt.Sprintf("%d", i) } //使用select来获取channel里面的数据的时候不需要关闭channel for { 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 + recover defer func() { //捕获test抛出的panic if err := recover(); err != nil { fmt.Println("test() 发生错误", err) } }() //定义了一个map var myMap map[int]string myMap[0] = "golang" //error}func main() { go sayHello() go test() //防止主进程退出这里使用time.Sleep演示,搭建也可以用sync.WaitGroup time.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 = 1 for 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()}