1. package main
    2. import (
    3. "fmt"
    4. "time"
    5. )
    6. // 在主线程(可以理解成进程)中,开启一个goroutine, 该协程每隔50毫秒秒输出 "你好golang"
    7. // 在主线程中也每隔50毫输出"你好golang", 输出10次后,退出程序
    8. // 要求主线程和goroutine同时执行
    9. func test() {
    10. for i := 0; i < 10; i++ {
    11. fmt.Println("test() 你好golang")
    12. time.Sleep(time.Millisecond * 100)
    13. }
    14. }
    15. func main() {
    16. go test() //表示开启一个协程
    17. for i := 0; i < 10; i++ {
    18. fmt.Println("main() 你好golang")
    19. time.Sleep(time.Millisecond * 100)
    20. }
    21. }
    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. "time"
    6. )
    7. //主线程退出后所有的协程无论有没有执行完毕都会退出,所以我们在主进程中可以通过WaitGroup等待协程执行完毕
    8. var wg sync.WaitGroup
    9. func test1() {
    10. for i := 0; i < 10; i++ {
    11. fmt.Println("test1() 你好golang-", i)
    12. time.Sleep(time.Millisecond * 100)
    13. }
    14. wg.Done() //协程计数器-1
    15. }
    16. func test2() {
    17. for i := 0; i < 10; i++ {
    18. fmt.Println("test2() 你好golang-", i)
    19. time.Sleep(time.Millisecond * 100)
    20. }
    21. wg.Done() //协程计数器-1
    22. }
    23. func main() {
    24. wg.Add(1) //协程计数器+1
    25. go test1() //表示开启一个协程
    26. wg.Add(1) //协程计数器+1
    27. go test2() //表示开启一个协程
    28. wg.Wait() //等待协程执行完毕...
    29. fmt.Println("主线程退出...")
    30. }
    1. package main
    2. import (
    3. "fmt"
    4. "runtime"
    5. )
    6. func main() {
    7. //获取当前计算机上面的Cup个数
    8. cpuNum := runtime.NumCPU()
    9. fmt.Println("cpuNum=", cpuNum)
    10. //可以自己设置使用多个cpu
    11. runtime.GOMAXPROCS(cpuNum - 1)
    12. fmt.Println("ok")
    13. }
    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. "time"
    6. )
    7. //多携程的一个案例
    8. var wg sync.WaitGroup
    9. func test(num int) {
    10. defer wg.Done()
    11. for i := 1; i <= 5; i++ {
    12. fmt.Printf("协程(%v)打印的第%v条数据\n", num, i)
    13. time.Sleep(time.Millisecond * 100)
    14. }
    15. }
    16. func main() {
    17. for i := 1; i <= 6; i++ {
    18. wg.Add(1)
    19. go test(i)
    20. }
    21. wg.Wait()
    22. fmt.Println("关闭主线程...")
    23. }
    1. package main
    2. import (
    3. "fmt"
    4. "time"
    5. )
    6. //需求:要统计1-120000的数字中那些是素数?for循环实现
    7. func main() {
    8. start := time.Now().Unix()
    9. for num := 2; num < 120000; num++ {
    10. var flag = true
    11. for i := 2; i < num; i++ {
    12. if num%i == 0 {
    13. flag = false
    14. break
    15. }
    16. }
    17. if flag {
    18. // fmt.Println(num, "是素数")
    19. }
    20. }
    21. end := time.Now().Unix()
    22. fmt.Println(end - start) //11毫秒 11毫秒
    23. }
    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. "time"
    6. )
    7. //需求:要统计1-120000的数字中那些是素数?goroutine for循环实现
    8. /*
    9. 1 协程 统计 1-30000
    10. 2 协程 统计 30001-60000
    11. 3 协程 统计 60001-90000
    12. 4 协程 统计 90001-120000
    13. // start:(n-1)*30000+1 end:n*30000
    14. */
    15. var wg sync.WaitGroup
    16. func test(n int) {
    17. for num := (n-1)*30000 + 1; num < n*30000; num++ {
    18. if num > 1 {
    19. var flag = true
    20. for i := 2; i < num; i++ {
    21. if num%i == 0 {
    22. flag = false
    23. break
    24. }
    25. }
    26. if flag {
    27. // fmt.Println(num, "是素数")
    28. }
    29. }
    30. }
    31. wg.Done()
    32. }
    33. func main() {
    34. start := time.Now().Unix()
    35. for i := 1; i <= 4; i++ {
    36. wg.Add(1)
    37. go test(i)
    38. }
    39. wg.Wait()
    40. fmt.Println("执行完毕")
    41. end := time.Now().Unix()
    42. fmt.Println(end - start) //4毫秒
    43. }
    1. package main
    2. import "fmt"
    3. func main() {
    4. //1、创建channel
    5. ch := make(chan int, 3)
    6. //2、给管道里面存储数据
    7. ch <- 10
    8. ch <- 21
    9. ch <- 32
    10. //3、获取管道里面的内容
    11. a := <-ch
    12. fmt.Println(a) //10
    13. <-ch //从管道里面取值 //21
    14. c := <-ch
    15. fmt.Println(c) //32
    16. ch <- 56
    17. ch <- 66
    18. //4、打印管道的长度和容量
    19. fmt.Printf("值:%v 容量:%v 长度%v\n", ch, cap(ch), len(ch)) //值:0xc0000d0080 容量:3 长度2
    20. // 5、管道的类型(引用数据类型)
    21. ch1 := make(chan int, 4)
    22. ch1 <- 34
    23. ch1 <- 54
    24. ch1 <- 64
    25. ch2 := ch1
    26. ch2 <- 69
    27. <-ch1
    28. <-ch1
    29. <-ch1
    30. d := <-ch1
    31. fmt.Println(d) //69
    32. //8、管道阻塞
    33. // ch6 := make(chan int, 1)
    34. // ch6 <- 34
    35. // ch6 <- 64 //all goroutines are asleep - deadlock!
    36. // 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告 deadlock
    37. // ch7 := make(chan string, 2)
    38. // ch7 <- "数据1"
    39. // ch7 <- "数据2"
    40. // m1 := <-ch7
    41. // m2 := <-ch7
    42. // m3 := <-ch7
    43. // fmt.Println(m1, m2, m3) //fatal error: all goroutines are asleep - deadlock!
    44. //正确的写法
    45. ch8 := make(chan int, 1)
    46. ch8 <- 34
    47. <-ch8
    48. ch8 <- 67
    49. <-ch8
    50. ch8 <- 78
    51. m4 := <-ch8
    52. fmt.Println(m4)
    53. }
    1. package main
    2. import "fmt"
    3. // 循环遍历管道数据
    4. func main() {
    5. //2、使用for range遍历通道,当通道被关闭的时候就会退出for range,如果没有关闭管道就会报个错误fatal error: all goroutines are asleep - deadlock!
    6. // var ch1 = make(chan int, 10)
    7. // for i := 1; i <= 10; i++ {
    8. // ch1 <- i
    9. // }
    10. // close(ch1) //关闭管道
    11. // //for range循环遍历管道的值 ,注意:管道没有key
    12. // for v := range ch1 {
    13. // fmt.Println(v)
    14. // }
    15. //2、通过for循环遍历管道的时候管道可以不关闭
    16. var ch2 = make(chan int, 10)
    17. for i := 1; i <= 10; i++ {
    18. ch2 <- i
    19. }
    20. for j := 0; j < 10; j++ {
    21. fmt.Println(<-ch2)
    22. }
    23. }
    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. )
    6. package main
    7. var wg sync.WaitGroup
    8. func putNum(intChan chan int) {
    9. for i := 2; i < 10; i++ {
    10. intChan <- i
    11. fmt.Println(i)
    12. }
    13. close(intChan)
    14. wg.Done()
    15. }
    16. //定义一个存放任意数据类型的管道 3个数据
    17. func main() {
    18. // allChan := make(chan interface{}, 3)
    19. // allChan <- 10
    20. // allChan <- "tom jack"
    21. // cat := Cat{"小花猫", 4}
    22. // allChan <- cat
    23. // //我们希望获得到管道中的第三个元素,则先将前2个推出
    24. // <-allChan
    25. // <-allChan
    26. // newCat := <-allChan //从管道中取出的Cat是什么?
    27. // fmt.Printf("newCat=%T , newCat=%v\n", newCat, newCat)
    28. // //下面的写法是错误的!编译不通过
    29. // //fmt.Printf("newCat.Name=%v", newCat.Name)
    30. // //使用类型断言
    31. // a := newCat.(Cat)
    32. // fmt.Printf("newCat.Name=%v", a.Name)
    33. var intChan = make(chan int, 1000)
    34. wg.Add(1)
    35. go putNum()
    36. wg.Wait()()
    37. }
    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. "time"
    6. )
    7. /*
    8. 需求:使用goroutine和channel协同工作案例
    9. 1、开启一个WriteData的的协程给向管道inChan中写入100条数据
    10. 2、开启一个ReadData的协程读取inChan中写入的数据
    11. 3、注意:WriteData和ReadData同时操作一个管道
    12. 4、主线程必须等待操作完成后才可以退出
    13. goroutine结合Channel使用的简单demo,定义两个方法,一个方法给管道里面写数据,一个给管道里面读取数据。要求同步进行。
    14. */
    15. var wg sync.WaitGroup
    16. //写数据
    17. func fn1(ch chan int) {
    18. for i := 1; i <= 10; i++ {
    19. ch <- i
    20. fmt.Printf("【写入】数据%v成功\n", i)
    21. time.Sleep(time.Millisecond * 5000)
    22. }
    23. close(ch)
    24. wg.Done()
    25. }
    26. func fn2(ch chan int) {
    27. for v := range ch {
    28. fmt.Printf("【读取】数据%v成功\n", v)
    29. time.Sleep(time.Millisecond * 10)
    30. }
    31. wg.Done()
    32. }
    33. func main() {
    34. var ch = make(chan int, 10)
    35. wg.Add(1)
    36. go fn1(ch)
    37. wg.Add(1)
    38. go fn2(ch)
    39. wg.Wait()
    40. fmt.Println("退出...")
    41. }
    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. "time"
    6. )
    7. var wg sync.WaitGroup
    8. func main() {
    9. // 1、创建channel
    10. var ch1 = make(chan int, 3)
    11. wg.Add(1)
    12. go func() {
    13. for i := 1; i <= 3; i++ {
    14. num := <-ch1
    15. fmt.Println(num)
    16. }
    17. wg.Done()
    18. }()
    19. wg.Add(1)
    20. go func() {
    21. for i := 1; i <= 3; i++ {
    22. time.Sleep(time.Second)
    23. ch1 <- i
    24. }
    25. wg.Done()
    26. }()
    27. wg.Wait()
    28. }
    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. "time"
    6. )
    7. var wg sync.WaitGroup
    8. //向 intChan放入 1-120000个数
    9. func putNum(intChan chan int) {
    10. for i := 2; i < 120000; i++ {
    11. intChan <- i
    12. }
    13. close(intChan)
    14. wg.Done()
    15. }
    16. // 从 intChan取出数据,并判断是否为素数,如果是,就把得到的素数放在primeChan
    17. func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {
    18. for num := range intChan {
    19. var flag = true
    20. for i := 2; i < num; i++ {
    21. if num%i == 0 {
    22. flag = false
    23. break
    24. }
    25. }
    26. if flag {
    27. primeChan <- num //num是素数
    28. }
    29. }
    30. //要关闭 primeChan
    31. // close(primeChan) //如果一个channel关闭了就没法给这个channel发送数据了
    32. //什么时候关闭primeChan?
    33. //给exitChan里面放入一条数据
    34. exitChan <- true
    35. wg.Done()
    36. }
    37. //printPrime打印素数的方法
    38. func printPrime(primeChan chan int) {
    39. // for v := range primeChan {
    40. // fmt.Println(v)
    41. // }
    42. wg.Done()
    43. }
    44. func main() {
    45. start := time.Now().Unix()
    46. intChan := make(chan int, 1000)
    47. primeChan := make(chan int, 50000)
    48. exitChan := make(chan bool, 16) //标识primeChan close
    49. //存放数字的协程
    50. wg.Add(1)
    51. go putNum(intChan)
    52. //统计素数的协程
    53. for i := 0; i < 16; i++ {
    54. wg.Add(1)
    55. go primeNum(intChan, primeChan, exitChan)
    56. }
    57. //打印素数的协程
    58. wg.Add(1)
    59. go printPrime(primeChan)
    60. //判断exitChan是否存满值
    61. wg.Add(1)
    62. go func() {
    63. for i := 0; i < 16; i++ {
    64. <-exitChan
    65. }
    66. //关闭primeChan
    67. close(primeChan)
    68. wg.Done()
    69. }()
    70. wg.Wait()
    71. end := time.Now().Unix()
    72. fmt.Println("执行完毕....", end-start, "毫秒")
    73. }
    1. package main
    2. import "fmt"
    3. //单向管道
    4. func main() {
    5. // 1、在默认情况下下,管道是双向
    6. ch1 := make(chan int, 2)
    7. ch1 <- 10
    8. ch1 <- 12
    9. m1 := <-ch1
    10. m2 := <-ch1
    11. fmt.Println(m1, m2) //10 12
    12. // 2、管道声明为只写
    13. ch2 := make(chan<- int, 2)
    14. ch2 <- 10
    15. ch2 <- 12
    16. // <-ch2 //receive from send-only type chan<- int
    17. // 3、管道声明为只读
    18. ch3 := make(<-chan int, 2)
    19. // ch3 <- 23
    20. }
    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. "time"
    6. )
    7. /*
    8. 需求:使用goroutine和channel协同工作案例
    9. 1、开启一个WriteData的的协程给向管道inChan中写入100条数据
    10. 2、开启一个ReadData的协程读取inChan中写入的数据
    11. 3、注意:WriteData和ReadData同时操作一个管道
    12. 4、主线程必须等待操作完成后才可以退出
    13. goroutine结合Channel使用的简单demo,定义两个方法,一个方法给管道里面写数据,一个给管道里面读取数据。要求同步进行。
    14. */
    15. var wg sync.WaitGroup
    16. //写数据
    17. func fn1(ch chan<- int) {
    18. for i := 1; i <= 10; i++ {
    19. ch <- i
    20. fmt.Printf("【写入】数据%v成功\n", i)
    21. time.Sleep(time.Millisecond * 50)
    22. }
    23. close(ch)
    24. wg.Done()
    25. }
    26. //读取管道里面的数据
    27. func fn2(ch <-chan int) {
    28. for v := range ch {
    29. fmt.Printf("【读取】数据%v成功\n", v)
    30. time.Sleep(time.Millisecond * 50)
    31. }
    32. wg.Done()
    33. }
    34. func main() {
    35. var ch = make(chan int, 10)
    36. wg.Add(1)
    37. go fn1(ch)
    38. wg.Add(1)
    39. go fn2(ch)
    40. wg.Wait()
    41. fmt.Println("退出...")
    42. }
    1. package main
    2. import (
    3. "fmt"
    4. "time"
    5. )
    6. func main() {
    7. // 在某些场景下我们需要同时从多个通道接收数据,这个时候就可以用到golang中给我们提供的select多路复用
    8. //1.定义一个管道 10个数据int
    9. intChan := make(chan int, 10)
    10. for i := 0; i < 10; i++ {
    11. intChan <- i
    12. }
    13. //2.定义一个管道 5个数据string
    14. stringChan := make(chan string, 5)
    15. for i := 0; i < 5; i++ {
    16. stringChan <- "hello" + fmt.Sprintf("%d", i)
    17. }
    18. //使用select来获取channel里面的数据的时候不需要关闭channel
    19. for {
    20. select {
    21. case v := <-intChan:
    22. fmt.Printf("从 intChan 读取的数据%d\n", v)
    23. time.Sleep(time.Millisecond * 50)
    24. case v := <-stringChan:
    25. fmt.Printf("从 stringChan 读取的数据%v\n", v)
    26. time.Sleep(time.Millisecond * 50)
    27. default:
    28. fmt.Printf("数据获取完毕")
    29. return //注意退出...
    30. }
    31. }
    32. }
    1. package main
    2. import (
    3. "fmt"
    4. "time"
    5. )
    6. //函数
    7. func sayHello() {
    8. for i := 0; i < 10; i++ {
    9. time.Sleep(time.Millisecond * 50)
    10. fmt.Println("hello,world")
    11. }
    12. }
    13. //函数
    14. func test() {
    15. //这里我们可以使用defer + recover
    16. defer func() {
    17. //捕获test抛出的panic
    18. if err := recover(); err != nil {
    19. fmt.Println("test() 发生错误", err)
    20. }
    21. }()
    22. //定义了一个map
    23. var myMap map[int]string
    24. myMap[0] = "golang" //error
    25. }
    26. func main() {
    27. go sayHello()
    28. go test()
    29. //防止主进程退出这里使用time.Sleep演示,搭建也可以用sync.WaitGroup
    30. time.Sleep(time.Second)
    31. }
    1. package main
    2. //go build -race main.go 编译后运行查看
    3. import (
    4. "fmt"
    5. "sync"
    6. "time"
    7. )
    8. var count = 0
    9. var wg sync.WaitGroup
    10. var mutex sync.Mutex
    11. func test() {
    12. mutex.Lock()
    13. count++
    14. fmt.Println("the count is : ", count)
    15. time.Sleep(time.Millisecond)
    16. mutex.Unlock()
    17. wg.Done()
    18. }
    19. func main() {
    20. for r := 0; r < 20; r++ {
    21. wg.Add(1)
    22. go test()
    23. }
    24. wg.Wait()
    25. }
    1. package main
    2. //go build -race main.go 编译后运行查看
    3. import (
    4. "fmt"
    5. "sync"
    6. "time"
    7. )
    8. var wg sync.WaitGroup
    9. var mutex sync.Mutex
    10. var m = make(map[int]int, 0)
    11. func test(num int) {
    12. mutex.Lock()
    13. var sum = 1
    14. for i := 1; i <= num; i++ {
    15. sum *= i
    16. }
    17. m[num] = sum
    18. // fmt.Println(m[num])
    19. fmt.Printf("key=%v value=%v\n", num, sum)
    20. time.Sleep(time.Millisecond)
    21. mutex.Unlock()
    22. wg.Done()
    23. }
    24. func main() {
    25. for r := 0; r < 40; r++ {
    26. wg.Add(1)
    27. go test(r)
    28. }
    29. wg.Wait()
    30. }
    1. package main
    2. import (
    3. "fmt"
    4. "sync"
    5. "time"
    6. )
    7. var wg sync.WaitGroup
    8. var mutex sync.RWMutex
    9. //写的方法
    10. func write() {
    11. mutex.Lock()
    12. fmt.Println("执行写操作")
    13. time.Sleep(time.Second * 2)
    14. mutex.Unlock()
    15. wg.Done()
    16. }
    17. //读的方法
    18. func read() {
    19. mutex.RLock()
    20. fmt.Println("---执行读操作")
    21. time.Sleep(time.Second * 2)
    22. mutex.RUnlock()
    23. wg.Done()
    24. }
    25. func main() {
    26. //开启10个协程执行读操作
    27. for i := 0; i < 10; i++ {
    28. wg.Add(1)
    29. go write()
    30. }
    31. // 开启10个协程执行写操作
    32. for i := 0; i < 10; i++ {
    33. wg.Add(1)
    34. go read()
    35. }
    36. wg.Wait()
    37. }