countfunc.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package main
  2. import (
  3. "bufio"
  4. "errors"
  5. "flag"
  6. "fmt"
  7. "io"
  8. "log"
  9. "os"
  10. "path"
  11. "path/filepath"
  12. "strings"
  13. "sync/atomic"
  14. "time"
  15. "github.com/google/gops/agent"
  16. "github.com/tal-tech/go-zero/core/mr"
  17. )
  18. var (
  19. dir = flag.String("d", "", "dir to enumerate")
  20. stopOnFile = flag.String("s", "", "stop when got file")
  21. maxFiles = flag.Int("m", 0, "at most files to process")
  22. mode = flag.String("mode", "", "simulate mode, can be return|panic")
  23. count uint32
  24. )
  25. func enumerateLines(filename string) chan string {
  26. output := make(chan string)
  27. go func() {
  28. file, err := os.Open(filename)
  29. if err != nil {
  30. return
  31. }
  32. defer file.Close()
  33. reader := bufio.NewReader(file)
  34. for {
  35. line, err := reader.ReadString('\n')
  36. if err == io.EOF {
  37. break
  38. }
  39. if !strings.HasPrefix(line, "#") {
  40. output <- line
  41. }
  42. }
  43. close(output)
  44. }()
  45. return output
  46. }
  47. func mapper(filename interface{}, writer mr.Writer, cancel func(error)) {
  48. if len(*stopOnFile) > 0 && path.Base(filename.(string)) == *stopOnFile {
  49. fmt.Printf("Stop on file: %s\n", *stopOnFile)
  50. cancel(errors.New("stop on file"))
  51. return
  52. }
  53. var result int
  54. for line := range enumerateLines(filename.(string)) {
  55. if strings.HasPrefix(strings.TrimSpace(line), "func") {
  56. result++
  57. }
  58. }
  59. switch *mode {
  60. case "return":
  61. if atomic.AddUint32(&count, 1)%10 == 0 {
  62. return
  63. }
  64. case "panic":
  65. if atomic.AddUint32(&count, 1)%10 == 0 {
  66. panic("wow")
  67. }
  68. }
  69. writer.Write(result)
  70. }
  71. func reducer(input <-chan interface{}, writer mr.Writer, cancel func(error)) {
  72. var result int
  73. for count := range input {
  74. v := count.(int)
  75. if *maxFiles > 0 && result >= *maxFiles {
  76. fmt.Printf("Reached max files: %d\n", *maxFiles)
  77. cancel(errors.New("max files reached"))
  78. return
  79. }
  80. result += v
  81. }
  82. writer.Write(result)
  83. }
  84. func main() {
  85. if err := agent.Listen(agent.Options{}); err != nil {
  86. log.Fatal(err)
  87. }
  88. flag.Parse()
  89. if len(*dir) == 0 {
  90. flag.Usage()
  91. }
  92. fmt.Println("Processing, please wait...")
  93. start := time.Now()
  94. result, err := mr.MapReduce(func(source chan<- interface{}) {
  95. filepath.Walk(*dir, func(fpath string, f os.FileInfo, err error) error {
  96. if !f.IsDir() && path.Ext(fpath) == ".go" {
  97. source <- fpath
  98. }
  99. return nil
  100. })
  101. }, mapper, reducer)
  102. if err != nil {
  103. fmt.Println(err)
  104. } else {
  105. fmt.Println(result)
  106. fmt.Println("Elapsed:", time.Since(start))
  107. fmt.Println("Done")
  108. }
  109. }