標籤:
一,過濾
package mainimport ( "flag" "fmt" "log" "os" "path/filepath" "runtime" "strings")func main() { runtime.GOMAXPROCS(runtime.NumCPU()) // Use all the machine‘s cores log.SetFlags(0) algorithm, minSize, maxSize, suffixes, files := handleCommandLine() if algorithm == 1 { sink(filterSize(minSize, maxSize, filterSuffixes(suffixes, source(files)))) } else { channel1 := source(files) channel2 := filterSuffixes(suffixes, channel1) channel3 := filterSize(minSize, maxSize, channel2) sink(channel3) }}func handleCommandLine() (algorithm int, minSize, maxSize int64, suffixes, files []string) { flag.IntVar(&algorithm, "algorithm", 1, "1 or 2") flag.Int64Var(&minSize, "min", -1, "minimum file size (-1 means no minimum)") flag.Int64Var(&maxSize, "max", -1, "maximum file size (-1 means no maximum)") var suffixesOpt *string = flag.String("suffixes", "", "comma-separated list of file suffixes") flag.Parse() if algorithm != 1 && algorithm != 2 { algorithm = 1 } if minSize > maxSize && maxSize != -1 { log.Fatalln("minimum size must be < maximum size") } suffixes = []string{} if *suffixesOpt != "" { suffixes = strings.Split(*suffixesOpt, ",") } files = flag.Args() return algorithm, minSize, maxSize, suffixes, files}func source(files []string) <-chan string { out := make(chan string, 1000) go func() { for _, filename := range files { out <- filename } close(out) }() return out}// make the buffer the same size as for files to maximize throughputfunc filterSuffixes(suffixes []string, in <-chan string) <-chan string { out := make(chan string, cap(in)) go func() { for filename := range in { if len(suffixes) == 0 { out <- filename continue } ext := strings.ToLower(filepath.Ext(filename)) for _, suffix := range suffixes { if ext == suffix { out <- filename break } } } close(out) }() return out}// make the buffer the same size as for files to maximize throughputfunc filterSize(minimum, maximum int64, in <-chan string) <-chan string { out := make(chan string, cap(in)) go func() { for filename := range in { if minimum == -1 && maximum == -1 { out <- filename // don‘t do a stat call it not needed continue } finfo, err := os.Stat(filename) if err != nil { continue // ignore files we can‘t process } size := finfo.Size() if (minimum == -1 || minimum > -1 && minimum <= size) && (maximum == -1 || maximum > -1 && maximum >= size) { out <- filename } } close(out) }() return out}func sink(in <-chan string) { for filename := range in { fmt.Println(filename) }}
這段過濾是一個很簡單大功能,設定一些參數就可以了。實現方式是類unix管道的方式,也就是串列。
首先使用了flag包把命令列參數解析出來,包括suffix,大小範圍和檔案名稱範圍,然後依次建立了3個channel。
第一個channel到寫端是把檔案名稱列表解析成一個一個的檔案名稱。
第二個channel的寫端,是把第一個檔案名稱按suffix做一次過濾後的結果。
第三個channel的寫端,是把第二個的檔案名稱按大小範圍過濾後的結果。
最後一個sink讀取第三個channel後,把結果列印出來。
嗯。。參數不同,有個分支只過濾了一次。。
關於flag包。。搜了下,解析參數時候是這樣的:首先參數定義有兩種,一種是帶有-符號的一種是沒有-符號的。flag的方法parse就是解析出來帶有-符號的,flag的args方法就是擷取其他參數的。好像就沒啥別的太特別的了~
關於channel和goroutin,好像這兒沒啥特別要說明的~
《go語言程式設計》學習(八)