《go语言程序设计》学习(三)

一,单词替换

  1 package main
  2 
  3 import (
  4     "bufio"
  5     "fmt"
  6     "io"
  7     "io/ioutil"
  8     "log"
  9     "os"
 10     "path/filepath"
 11     "regexp"
 12     "strings"
 13 )
 14 
 15 var britishAmerican = "british-american.txt"
 16 
 17 func init() {
 18     dir, _ := filepath.Split(os.Args[0])
 19     britishAmerican = filepath.Join(dir, britishAmerican)
 20     //fmt.Println("dir %s,file %s",dir,britishAmerican)
 21 }
 22 
 23 func main() {
 24     inFilename, outFilename, err := filenamesFromCommandLine()
 25     if err != nil {
 26         fmt.Println(err)
 27         os.Exit(1)
 28     }
 29     inFile, outFile := os.Stdin, os.Stdout
 30     if inFilename != "" {
 31         if inFile, err = os.Open(inFilename); err != nil {
 32             log.Fatal(err)
 33         }
 34         defer inFile.Close()
 35     }
 36     if outFilename != "" {
 37         if outFile, err = os.Create(outFilename); err != nil {
 38             log.Fatal(err)
 39         }
 40         defer outFile.Close()
 41     }
 42 
 43     if err = americanise(inFile, outFile); err != nil {
 44         log.Fatal(err)
 45     }
 46 }
 47 
 48 func filenamesFromCommandLine() (inFilename, outFilename string, err error) {
 49     if len(os.Args) > 1 && (os.Args[1] == "-h" || os.Args[1] == "--help") {
 50         err = fmt.Errorf("usage :%s [<] infile.txt [>] outfile.txt",
 51             filepath.Base(os.Args[0]))
 52         return "", "", err
 53     }
 54     if len(os.Args) > 1 {
 55         inFilename = os.Args[1]
 56         if len(os.Args) > 2 {
 57             outFilename = os.Args[2]
 58         }
 59     }
 60     if inFilename != "" && inFilename == outFilename {
 61         log.Fatal("won't overwrite the infile")
 62     }
 63     return inFilename, outFilename, nil
 64 }
 65 
 66 func americanise(inFile io.Reader, outFile io.Writer) (err error) {
 67     reader := bufio.NewReader(inFile)
 68     writer := bufio.NewWriter(outFile)
 69     defer func() {
 70         if err == nil {
 71             err = writer.Flush()
 72         }
 73     }()
 74 
 75     var replacer func(string) string
 76     if replacer, err = makeReplacerFunction(britishAmerican); err != nil {
 77         return err
 78     }
 79     wordRx := regexp.MustCompile("[A-Za-z]+")
 80     eof := false
 81     for !eof {
 82         var line string
 83         line, err = reader.ReadString('\n')
 84         if err == io.EOF {
 85             err = nil
 86             eof = true
 87         } else if err != nil {
 88             return err
 89         }
 90         line = wordRx.ReplaceAllStringFunc(line, replacer)
 91         if _, err = writer.WriteString(line); err != nil {
 92 
 93             return err
 94         }
 95     }
 96     return nil
 97 }
 98 
 99 func makeReplacerFunction(file string) (func(string) string, error) {
100     rawBytes, err := ioutil.ReadFile(file)
101     if err != nil {
102         return nil, err
103     }
104     text := string(rawBytes)
105     usForBritish := make(map[string]string)
106     lines := strings.Split(text, "\n")
107     for _, line := range lines {
108         fields := strings.Fields(line)
109         if len(fields) == 2 {
110             usForBritish[fields[0]] = fields[1]
111         }
112     }
113 
114     return func(word string) string {
115         if usWord, found := usForBritish[word]; found {
116             return usWord
117         }
118         return word
119     }, nil
120 }

 

这次的格式终于没错

这个功能里面,我觉得有几个要点,一个是闭包,一个是正则的替换,还有个defer做后事~

简单理解一下闭包,在构造一个函数的时候,同时让这个函数自带了一些数据等其他内容,比如这里定义这个replacer函数的时候,首先定义replacer的私有数据map,然后返回了使用这个map的函数。这样在调用replacer的时候,就可以使用这个map点数据。(好像说的有点混乱。。)

正则和defer就没啥好说的了。。

posted @ 2015-08-02 10:17  诡城  阅读(300)  评论(0编辑  收藏  举报