04 - 查找重复行2 深一步了解go

  • 接上一节任务运行后续

在上一节中 dup1 从标准输入当中获取数据,而在 dup2 当中我们读取标准输入或是使用os.Open打开各个具名文件,并操作它们。

一、dup2

运行路径:

$GOPATH/src/gopl/ch1/dup

运行方式

$ go run dup2.go input.txt

尝试了上述的运行方式,我们得到以下的运行结果 在这里插入图片描述

二、程序分析

以下是程序从标准输入或者某个文件中读取数据处理的源代码:

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    counts := make(map[string]int)
    files := os.Args[1:]
    if len(files) == 0 {
        countLines(os.Stdin, counts)
    }else {
        for _,arg := range files {
            f, err := os.Open(arg)
            if err != nil {
                fmt.Fprintf(os.Stderr, "dup2: %v\n", err)
                continue
            }
            countLines(f, counts)
            f.Close()
        }
    }

    for line, n := range counts{
        if n > 1{
            fmt.Printf("%d\t%s\n", n, line)
        }
    }
}

func countLines(f *os.File, counts map[string]int) {
    input := bufio.NewScanner(f)
    for input.Scan() {
        counts[input.Text()]++
    }
}

1. os.Args中的数组slice

files := os.Args[1:] 表示返回的是输入参数的 数组slice, 类似于引用。在 go 语言当中 ,os.Args[m:n] 表示返回输入参数列表中 [m, n) 个参数的一个 数组slice, os.Args[m:] 表示返回输入参数列表中第m个到最后一个参数的数组sliceos.Args[:n] 表示返回输入参数列表中 [1, n) 个参数的一个 数组slice

2. os.Open

os.Open 函数返回了两个参数,第二个参数是内置 error 类型的值。如果 err 等于内置值 nil ,表示文件打开成功,直到处理完所有数据后, 调用 Close 关闭该文件,并释放所占有的所有资源。反而言之如果 err 的值不是等于 nil 值,就代表打开文件出错,就需要有对应的处理方式.

f, err := os.Open(arg)
if err != nil {
	fmt.Fprintf(os.Stderr, "dup2: %v\n", err)
	continue
}

3. countLines 函数中的map[string]int

map 是一个由 make 函数创建的数据结构的引用。map 作为为参数传递给某函数时,该函数接收这个引用的一份拷贝( copy ,或译为副本),被调用函数对 map 底层数据结构的任何修改,调用者函数都可以通过持有的 map 引用看到。在我们的例子中,countLines 函数向 counts 插入的值,也会被 ** main** 函数看到。(译注:类似于 C++ 里的引用传递,实际上指针是另一个指针了,但内部存的值指向同一块内存)

4. fmt.Printf

类似于 C 或其它语言里的 printf 函数, fmt.Printf 函数对一些表达式产生格式化输出。该函数的首个参数是个格式字符串,指定后续参数被如何格式化。按照惯例,以字母 f 结尾的格式化函数,如 log.Printffmt.Errorf ,都采用 fmt.Printf 的格式化准则。而以 ln 结尾的格式化函数,则遵循 Println 的方式,以跟 %v 差不多的方式格式化参数,并在最后添加一个换行符。

%d 十进制整数
%x, %o, %b 十六进制,八进制,二进制整数。
%f, %g, %e 浮点数: 3.141593 3.141592653589793 3.141593e+00
%t 布尔:true或false
%c 字符(rune) (Unicode码点)
%s 字符串
%q 带双引号的字符串"abc"或带单引号的字符’c’
%v 变量的自然形式(natural format)
%T 变量的类型
%% 字面上的百分号标志(无操作数)

5. for循环中 “_” 的使用

for 循环当中我们使用 “_” , 因为 range 对返回了两个参数,第二个参数是 value, 第一个参数就是索引号, “_” 就像是 Linux 中的 /dev/null 一样像个无底洞,

for _,arg := range files {
	//_ 代表就是 files 的索引值
}

总结

  • 理解 “_” 的含义
  • map[string]int的引用传值
  • Printf 函数的格式, 特别注意 %v %T
  • 理解数组切片

猜你喜欢

转载自blog.csdn.net/xiaomiCJH/article/details/85798072