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

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语法用于遍历切片和数组非常方便,每次迭代它会返回切片的索引和在该切片上的元素值。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值