您的位置:首页 > 编程语言 > Go语言

Go语言基础学习二-简单的代码分析

2017-03-20 18:00 676 查看
Go语言基础学习二
一点经验:
    main()函数作为整个程序的入口,没有参数,也没有返回值,还有一个函数init()先于main()执行,以后待讲。
    导入包中fmt提供格式化文本和读入格式文本的函数,os包提供了跨平台的操作系统层面变量及函数,包括保存命令行参数的类型os.Args 
strings包提供处理字符串的函数。
    go程序中不含有分号,分号由编译器自动添加。
    filepath.Base()函数会返回传入路径的基础名,Go语言采用单引号表达字符,Go语言具有强类型转换,将int16与int32不能直接相加,需要进行类型转换。
     栈-自定义类型及其方法,自定义栈可以通过空接口来实现将异构(类型不同的)的元素混合存储,因为go语言的所有类型都实现了空接口。
     func (stack *Stack) Top() (interface{},error){
       return stack[len(stack)-1],nil
}   函数的声明,第一个圆括号 stack *Stack表示一个类型为指向Stack的参数,名为stack,最后一个圆括号表示返回的值,返回两个值,一个是空接口,一个是错误信息。
      切片(在我的理解,就是数组),切片的内容可以通过索引来表示[first:end]一定范围的值。
      buffo包提供了带缓冲的I/O处理能力,io包提供了底层I/O能力,包含有io.Reader及io.Writer接口,io/ioutil包提供了一系列高级文件处理函数。regexp包则提供了强大的正则表达式支持。
package main

import (
    "bufio"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "os"
    "path/filepath"
    "regexp"
    "strings"
)
var britishAmerican = "british-american.txt"

func init() {/*进入函数main()之前,首先要执行init()内部的内容,获取当前目录并构建单词转化所需的文本路径*/
    dir, _ := filepath.Split(os.Args[0])
    britishAmerican = filepath.Join(dir, britishAmerican)
}

func main() {
    inFilename, outFilename, err := filenamesFromCommandLine()
/*调用filenamesFromCommandLine()函数获取命令行中的数据输入文件和输出文件,返回值为输入文件名和输出文件名及错误信息*/
    if err != nil {/*当错误信息不为空时,输出并退出程序*/
        fmt.Println(err)
        os.Exit(1)
    }
    inFile, outFile := os.Stdin, os.Stdout
    if inFilename != "" {
        /*打开只读输入文件,返回指向文件的指针和错误信息*/
        if inFile, err = os.Open(inFilename); err != nil {
            log.Fatal(err)
        }
        /*defer是指推迟执行,直到main()函数正常返回会调用该执行语句,关闭文件,回收内存,当程序崩溃时,不会执行,但是go语言系统会自动关闭所有打开的文件,垃圾回收器会回收内存*/
        defer inFile.Close()
    }
    if outFilename != "" {
        /*os.Create()读取一个文件,若文件不存在创建该文件,若存在,将该文件长度截为0*/
        if outFile, err = os.Create(outFilename); err != nil {
            log.Fatal(err)
        }
        defer outFile.Close()
    }
     /*americanise该函数用于替换英式单词为美式单词*/
    if err = americanise(inFile, outFile); err != nil {
        log.Fatal(err)
    }
}

/*该函数用于分析命令行*/
func filenamesFromCommandLine() (inFilename, outFilename string,
    err error) {
    /*os.Args保存有命令行参数,命令行参数大于1,且可以分析-h及--help等参数为命令解释请求*/
    if len(os.Args) > 1 && (os.Args[1] == "-h" || os.Args[1] == "--help") {
        err = fmt.Errorf("usage: %s [<]infile.txt [>]outfile.txt",
            filepath.Base(os.Args[0]))
        return "", "", err
    }
    if len(os.Args) > 1 {
        inFilename = os.Args[1]
        if len(os.Args) > 2 {
            outFilename = os.Args[2]
        }
    }
    if inFilename != "" && inFilename == outFilename {
        log.Fatal("won't overwrite the infile")
    }
    return inFilename, outFilename, nil
}

/*该函数实现替换英式单词为美式单词*/
func americanise(inFile io.Reader, outFile io.Writer) (err error) {
    /*向bufio.NewReader传入实现io.Rreader接口的值,提供缓冲机制*/
    reader := bufio.NewReader(inFile)
    writer := bufio.NewWriter(outFile)
    /*延迟至main()函数返回,刷新写缓冲区,确保全部写入*/
    defer func() {
        if err == nil {
            err = writer.Flush()
        }
    }()
    /*定义一个替换器函数,参数为string,返回string*/
    var replacer func(string) string
    /*makeReplacerFunction根据单词替换文本britishAmerican生成替换器replacer*/
    if replacer, err = makeReplacerFunction(britishAmerican); err != nil {
        return err
    }
    /*正则表达式*/
    wordRx := regexp.MustCompile("[A-Za-z]+")
    eof := false
    /*循环读取文件,直到读到文件末尾*/
    for !eof {
        var line string
        line, err = reader.ReadString('\n')
        if err == io.EOF {
            err = nil   // io.EOF isn't really an error
            eof = true  // this will end the loop at the next iteration
        } else if err != nil {
            return err  // finish immediately for real errors
        }
        /*对读取的每一行进行替换器替换并写入输出文件*/
        line = wordRx.ReplaceAllStringFunc(line, replacer)
        /*这里的_表示空标记符,作为一个占位符放在一个需要变量的地方,并忽略掉该变量的值。*/
        if _, err = writer.WriteString(line); err != nil {
            return err
        }
    }
    return nil
}
/*根据单词替换文本生成替换器replacer*/
func makeReplacerFunction(file string) (func(string) string, error) {
    /*首先读取单词替换文本*/
    rawBytes, err := ioutil.ReadFile(file)
    if err != nil {
        return nil, err
    }
    text := string(rawBytes)
    /*创建一个映射对象*/
    usForBritish := make(map[string]string)
    /*将文本逐行分解*/
    lines := strings.Split(text, "\n")
    for _, line := range lines {
        /*每一行将根据空格符生成对应切片,strings.Fields这个函数就是以空白分割符来分隔字符串*/
        fields := strings.Fields(line)
        if len(fields) == 2 {
            /*将切片填充到映射对象中去*/
            usForBritish[fields[0]] = fields[1]
        }
    }

    return func(word string) string {
        /*根据映射对象的映射关系生成替换器*/
        if usWord, found := usForBritish[word]; found {
            return usWord
        }
        return word
    }, nil
}
go语言中字符串类型的内部表示统一为utf-8编码的。
go语言中的映射,切片和通道都是要通过make()函数来创建的。
for。。range语法用于遍历切片和数组非常方便,每次迭代它会返回切片的索引和在该切片上的元素值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  go语言