练习题1

要求:
1、启动1个协程,将1~2000个数放进channel里,比如为newChan
2、启动10个协程,从newChan中取出数据n,并计算1+..+n的值,将其存入新的channel中,比如retChan
3、打印retChan的结果,比如ret[1]=1….

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. /*
  7. 练习题:
  8. 1、启动1个协程,将1~2000个数放进channel里,比如为newChan
  9. 2、启动10个协程,从newChan中取出数据n,并计算1+..+n的值,将其存入新的channel中,比如retChan
  10. 3、打印retChan的结果,比如ret[1]=1....
  11. */
  12. var wg sync.WaitGroup
  13. func writeData(newChan chan int) {
  14. // 向里面写入1~2000个数字
  15. for i := 1; i <= 2000; i++ {
  16. newChan <- i
  17. }
  18. close(newChan)
  19. }
  20. func readData(newChan chan int, retChan chan map[int]int) {
  21. for {
  22. data, ok := <-newChan
  23. if !ok {
  24. break
  25. }
  26. ret := 0
  27. for i := 0; i < data; i++ {
  28. ret += i
  29. }
  30. retMap := make(map[int]int)
  31. retMap[data] = ret
  32. retChan <- retMap
  33. defer wg.Done()
  34. }
  35. // close(retChan)
  36. }
  37. func main() {
  38. // 初始channel
  39. newChan := make(chan int, 2000)
  40. retChan := make(chan map[int]int, 2000)
  41. wg.Add(2000)
  42. go writeData(newChan)
  43. // 开启8个线程去读写
  44. for i := 0; i < 8; i++ {
  45. go readData(newChan, retChan)
  46. }
  47. wg.Wait()
  48. close(retChan)
  49. for data := range retChan {
  50. // fmt.Println(data)
  51. for key, value := range data {
  52. fmt.Printf("ret[%d]=%d\n", key, value)
  53. }
  54. }
  55. }

练习题2

要求:
1、开启1个协程writeDataToFile,随机生产1000个数字,存放到文件中
2、当writeDataToFile完成1000个数字写入后,让sort协程从中读取1000个数据对其进行排序,并将排序好的数字存入新的文件中

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "math/rand"
  7. "os"
  8. "sort"
  9. "strconv"
  10. "strings"
  11. "sync"
  12. )
  13. /*
  14. 1、开启1个协程writeDataToFile,随机生产1000个数字,存放到文件中
  15. 2、当writeDataToFile完成1000个数字写入后,让sort协程从中读取1000个数据对其进行排序,并将排序好的数字存入新的文件中
  16. */
  17. var wg sync.WaitGroup
  18. func writeDataToFile(fileChan chan bool) {
  19. writeFile, err := os.OpenFile("./random.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
  20. if err != nil {
  21. fmt.Println("open file failed, err:", err)
  22. return
  23. }
  24. defer writeFile.Close()
  25. for i := 1; i <= 1000; i++ {
  26. // 生成随机数
  27. randomNum := rand.Int31() % 10000
  28. // 将随机数保存到文件中
  29. writeFile.WriteString(strconv.Itoa(int(randomNum)) + "\n")
  30. }
  31. fileChan <- true
  32. close(fileChan)
  33. }
  34. func sortData(fileChan chan bool) {
  35. for {
  36. ret, ok := <-fileChan
  37. if !ok {
  38. break
  39. }
  40. if ret {
  41. readFile, err := os.Open("./random.txt")
  42. if err != nil {
  43. fmt.Println("read file failed, err:", err)
  44. }
  45. defer readFile.Close()
  46. newFile, err := os.OpenFile("./newfile.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
  47. if err != nil {
  48. fmt.Println("open new file failed, err:", err)
  49. return
  50. }
  51. defer newFile.Close()
  52. newReader := bufio.NewReader(readFile)
  53. // 逐行读取,将其转换为int,存到slice中
  54. var newSlice []int
  55. for {
  56. line, err := newReader.ReadString('\n')
  57. if err == io.EOF {
  58. break
  59. }
  60. if err != nil {
  61. fmt.Println(err)
  62. }
  63. // fmt.Println()
  64. ret, _ := strconv.Atoi(strings.Split(line, "\n")[0])
  65. // fmt.Println(ret)
  66. // fmt.Printf("%T\n", ret)
  67. newSlice = append(newSlice, ret)
  68. }
  69. // fmt.Println(newSlice)
  70. // 对切片进行排序
  71. // fmt.Println(len(newSlice))
  72. sort.Ints(newSlice)
  73. // fmt.Println(len(newSlice))
  74. // 将排序好的数据写入新文件
  75. for _, v := range newSlice {
  76. newFile.WriteString(strconv.Itoa(v) + "\n")
  77. }
  78. defer wg.Done()
  79. // close(exitChan)
  80. }
  81. }
  82. }
  83. func main() {
  84. // 定义一个channel,用来记录文件已经写完
  85. fileChan := make(chan bool, 1)
  86. // exitChan := make(chan bool, 1)
  87. wg.Add(1)
  88. go writeDataToFile(fileChan)
  89. // go sortData(fileChan, exitChan)
  90. go sortData(fileChan)
  91. // for {
  92. // _, ok := <-exitChan
  93. // if !ok {
  94. // break
  95. // }
  96. // }
  97. wg.Wait()
  98. }

扩展:
1、开启10个协程writeDataToFile,随机生产1000个数字,存放到10文件中
2、当writeDataToFile完成10个文件1000个数字写入后,让sort协程从10个文件中读取1000个数据对其进行排序,并将排序好的数字存入新的10的文件中

练习题3

使用goroutine和channel实现一个计算int64随机数各位数和的程序。
1、开启一个goroutine循环生成int64类型的随机数,发送到jobChan
2、开启24个goroutine从jobChan中取出随机数计算各位数的和,将结果发送到resultChan
3、主goroutine从resultChan取出结果并打印到终端输出

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "sync"
  6. "time"
  7. )
  8. /*
  9. 使用goroutine和channel实现一个计算int64随机数各位数和的程序。
  10. 1、开启一个goroutine循环生成int64类型的随机数,发送到jobChan
  11. 2、开启24个goroutine从jobChan中取出随机数计算各位数的和,将结果发送到resultChan
  12. 3、主goroutine从resultChan取出结果并打印到终端输出
  13. */
  14. type job struct {
  15. value int64
  16. }
  17. type result struct {
  18. job *job
  19. sum int64
  20. }
  21. var wg sync.WaitGroup
  22. func insertData(ch1 chan<- *job) {
  23. defer wg.Done()
  24. // 循环写
  25. for {
  26. // 生成随机数
  27. num := rand.Int63()
  28. // 实例化job
  29. numJob := &job{
  30. value: num,
  31. }
  32. ch1 <- numJob
  33. time.Sleep(time.Millisecond * 500)
  34. }
  35. }
  36. func sumData(ch1 <-chan *job, retChan chan<- *result) {
  37. defer wg.Done()
  38. for {
  39. // 循环从ch1读数据
  40. num := <-ch1
  41. sum := int64(0)
  42. // 计算位数之和
  43. n := num.value
  44. for n > 0 {
  45. sum += n % 10
  46. n = n / 10
  47. }
  48. // 实例化result
  49. newResult := &result{
  50. job: num,
  51. sum: sum,
  52. }
  53. retChan <- newResult
  54. }
  55. }
  56. func main() {
  57. inChan := make(chan *job, 100)
  58. retChan := make(chan *result, 100)
  59. wg.Add(1)
  60. go insertData(inChan)
  61. for i := 1; i <= 24; i++ {
  62. wg.Add(1)
  63. go sumData(inChan, retChan)
  64. }
  65. // 打印结果
  66. for ret := range retChan {
  67. fmt.Printf("Job: [%d] Sum: [%d]\n", ret.job.value, ret.sum)
  68. }
  69. wg.Wait()
  70. }