GoLang之Concurrency顺序管道模式

前端之家收集整理的这篇文章主要介绍了GoLang之Concurrency顺序管道模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

2013-12-14 wcdj


本文介绍go利用管道如何进行并发计算,需要注意go的管道是双向的,而UNIX管道是单向的。

PS: 在测试时自己建立了一个后缀为_test.go的文件,build后会提示如下错误

一句话解释:在go中文件名后缀为_test.go的都是单元测试文件

具体可参考:http://segmentfault.com/q/1010000000159135


本例参考《go语言程序设计》第七章的一个例子,并添加了一些注释。

  1. package main
  2.  
  3. import (
  4. "flag"
  5. "fmt"
  6. "log"
  7. "os"
  8. "path/filepath"
  9. "runtime"
  10. "strings"
  11. )
  12.  
  13. func main() {
  14.  
  15. // Use all the machine's cores
  16. runtime.GOMAXPROCS(runtime.Numcpu())
  17. log.SetFlags(0)
  18.  
  19. // 处理命令行参数
  20. algorithm,minSize,maxSize,suffixes,files := handleCommandLine()
  21.  
  22. // 开始计算操作
  23. if algorithm == 1 {
  24. // 算法1是并行计算,通过创建各个的goroutine
  25.  
  26. // step1: 先通过source函数处理文件列表,并把处理结果返回到管道里
  27. // step2: 将符合后缀的文件放到管道里
  28. // step3: 将符合大小的文件放到管道里
  29. // step4: 从管道获取结果数据
  30. sink(filterSize(minSize,filterSuffixes(suffixes,source(files))))
  31. } else {
  32.  
  33. // 算法2是串行计算
  34. channel1 := source(files)
  35. channel2 := filterSuffixes(suffixes,channel1)
  36. channel3 := filterSize(minSize,channel2)
  37. sink(channel3)
  38. }
  39. }
  40.  
  41. // 命令行参数解析操作
  42. func handleCommandLine() (algorithm int,maxSize int64,files []string) {
  43.  
  44. // 将命令行参数绑定到对应的变量中
  45. // algorithm默认为1
  46. flag.IntVar(&algorithm,"algorithm",1,"1 or 2")
  47. // minSize和maxSize默认为-1,表示没有限制
  48. flag.Int64Var(&minSize,"min",-1,"minimum file size (-1 means no minimum)")
  49. flag.Int64Var(&maxSize,"max","maximum file size (-1 means no maximum)")
  50. // suffixes后缀列表默认为空
  51. var suffixesOpt *string = flag.String("suffixes","","comma-separated list of file suffixes")
  52.  
  53. // 命令行预处理
  54. flag.Parse()
  55.  
  56. if algorithm != 1 && algorithm != 2 {
  57. algorithm = 1
  58. }
  59. if minSize > maxSize && maxSize != -1 {
  60. // Fatalln is equivalent to Println() followed by a call to os.Exit(1)
  61. log.Fatalln("minimum size must be < maximum size")
  62. }
  63.  
  64. // 将后缀列表用逗号分隔,返回suffixes后缀切片
  65. suffixes = []string{}
  66. if *suffixesOpt != "" {
  67. suffixes = strings.Split(*suffixesOpt,",")
  68. }
  69.  
  70. // Args returns the non-flag command-line arguments
  71. // 认为非命令选项的参数全为文件参数
  72. files = flag.Args()
  73. return algorithm,files
  74. }
  75.  
  76. // 创建管道,处理文件列表并把结果返回到管道里
  77. func source(files []string) <-chan string {
  78. out := make(chan string,1000)
  79. go func() {
  80. for _,filename := range files {
  81. out <- filename
  82. }
  83. close(out)
  84. }()
  85. return out
  86. }
  87.  
  88. // 将符合后缀的文件放到管道里
  89. // 根据后缀切片处理管道里的文件,同样再把结果返回到管道里
  90. // make the buffer the same size as for files to maximize throughput
  91. func filterSuffixes(suffixes []string,in <-chan string) <-chan string {
  92. out := make(chan string,cap(in))
  93. go func() {
  94. for filename := range in {
  95.  
  96. // 没有限制后缀的话,则直接将文件塞到管道里
  97. if len(suffixes) == 0 {
  98. out <- filename
  99. continue
  100. }
  101.  
  102. // 获取文件列表的后缀,且全部转换为小写
  103. // Ext returns the file name extension used by path. The extension is the suffix beginning at the final dot in the final element of path; it is empty if there is no dot
  104. ext := strings.ToLower(filepath.Ext(filename))
  105. for _,suffix := range suffixes {
  106. if ext == suffix {
  107. out <- filename
  108. break
  109. }
  110. }
  111. }
  112. close(out)
  113. }()
  114. return out
  115. }
  116.  
  117. // 将符合文件大小的文件放到管道里
  118. // make the buffer the same size as for files to maximize throughput
  119. func filterSize(minimum,maximum int64,cap(in))
  120. go func() {
  121. for filename := range in {
  122.  
  123. // 对文件大小没有限制,直接将文件塞到管道里
  124. if minimum == -1 && maximum == -1 {
  125. out <- filename // don't do a stat call it not needed
  126. continue
  127. }
  128.  
  129. // 使用操作系统的接口获取文件大小等信息
  130. // Stat returns a FileInfo describing the named file. If there is an error,it will be of type *PathError
  131. /*
  132. type FileInfo interface {
  133. Name() string // base name of the file
  134. Size() int64 // length in bytes for regular files; system-dependent for others
  135. Mode() FileMode // file mode bits
  136. ModTime() time.Time // modification time
  137. IsDir() bool // abbreviation for Mode().IsDir()
  138. Sys() interface{} // underlying data source (can return nil)
  139. }
  140. */
  141. finfo,err := os.Stat(filename)
  142. if err != nil {
  143. continue // ignore files we can't process
  144. }
  145. size := finfo.Size()
  146. if (minimum == -1 || minimum > -1 && minimum <= size) &&
  147. (maximum == -1 || maximum > -1 && maximum >= size) {
  148. out <- filename
  149. }
  150. }
  151. close(out)
  152. }()
  153. return out
  154. }
  155.  
  156. // 从管道获取结果数据
  157. func sink(in <-chan string) {
  158. for filename := range in {
  159. fmt.Println(filename)
  160. }
  161. }
  162.  
  163. /*
  164. output:
  165. mba:go gerryyang$ ./filter_t -min 1 -suffixes ".cpp" ../c++11/range_for.cpp ../c++11/test ../c++11/test.cpp routines.go
  166. ../c++11/range_for.cpp
  167. ../c++11/test.cpp
  168. mba:go gerryyang$ ./filter_t -min 1 -max -2 -suffixes ".cpp" ../c++11/range_for.cpp ../c++11/test ../c++11/test.cpp routines.go jjjj
  169. minimum size must be < maximum size
  170. */


在网上发现一个go的学习站点,有空可以逛下:http://blog.studygolang.com/

猜你在找的Go相关文章