zoukankan      html  css  js  c++  java
  • 《go语言程序设计》学习(八)

    一,过滤

    package main
    
    import (
        "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 throughput
    func 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 throughput
    func 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,好像这儿没啥特别要说明的~

  • 相关阅读:
    求逆序对
    2018浙江省赛(ACM) The 15th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple
    江西财经大学第一届程序设计竞赛
    EOJ Monthly 2018.4
    AtCoder Regular Contest 096
    “今日头条杯”首届湖北省大学程序设计竞赛(网络同步赛)
    Wannafly挑战赛14
    是男人就过 8 题--Pony.AI A AStringGame
    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛
    第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛
  • 原文地址:https://www.cnblogs.com/mruoli/p/4709362.html
Copyright © 2011-2022 走看看