00:00:00
入门
Echo 程序
echo 程序实现了输出命令行参数的功能。
go
package main
import (
"fmt"
"os"
"strings"
"time"
)
func main() {
// 三种不同的实现方式
echoFor()
echoForRange()
echoJoin()
// 打印程序名
echo()
// 打印索引和值
echoForRangeKV()
// 简单的使用 time 包对比不同实现的性能
echoForTime()
echoForRangeTime()
echoJoinTime()
}
func echoFor() {
var s, sep string
for _, arg := range os.Args[1:] {
s += sep + arg
sep = " "
}
fmt.Println(s)
}
func echoForRange() {
var s, sep string
for _, arg := range os.Args[1:] {
s += sep + arg
sep = " "
}
fmt.Println(s)
}
func echoJoin() {
fmt.Println(strings.Join(os.Args[1:], " "))
}
func echo() {
fmt.Println(os.Args[0])
}
func echoForRangeKV() {
for i, arg := range os.Args[1:] {
fmt.Printf("index: %d, value: %s\n", i+1, arg)
}
}
func echoForTime() {
start := time.Now()
var s, sep string
for _, arg := range os.Args[1:] {
s += sep + arg
sep = " "
}
fmt.Println(s)
fmt.Println(time.Since(start))
}
func echoForRangeTime() {
start := time.Now()
var s, sep string
for _, arg := range os.Args[1:] {
s += sep + arg
sep = " "
}
fmt.Println(s)
fmt.Println(time.Since(start))
}
func echoJoinTime() {
start := time.Now()
fmt.Println(strings.Join(os.Args[1:], " "))
fmt.Println(time.Since(start))
}运行 echo 程序:
bash
a b c
a b c
a b c
/var/folders/3n/7gjxlkgd5216cxw0gx9lzf9m0000gn/T/go-build929972194/b001/exe/main
index: 1, value: a
index: 2, value: b
index: 3, value: c
a b c
21.167µs
a b c
1.916µs
a b c
1.667µs三种不同的实现方式的性能对比:
- echoFor:使用 for 循环遍历命令行参数,每次迭代拼接一个参数,最后输出结果。
- echoForRange:使用 for range 循环遍历命令行参数,每次迭代拼接一个参数,最后输出结果。
- echoJoin:使用 strings.Join 函数将命令行参数拼接成一个字符串,最后输出结果。
从运行结果可以看出,echoJoin 的性能最优,而 echoForRange 的性能次之,echoFor 的性能最差。
Dup 程序
dup 程序实现了统计标准输入中重复出现的行的功能。
go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
dupStdin()
dupStdinOrFile()
}
func dupStdin() {
counts := make(map[string]int)
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
counts[input.Text()]++
}
for line, n := range counts {
if n > 1 {
fmt.Printf("%d\t%s\n", n, line)
}
}
}
func dupStdinOrFile() {
counts := make(map[string]int)
files := os.Args[1:]
if len(files) == 0 {
countLines(os.Stdin, counts)
} else {
for _, filename := range files {
file, err := os.Open(filename)
if err != nil {
fmt.Fprintf(os.Stderr, "dup: %v\n", err)
continue
}
countLines(file, counts)
file.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()]++
}
}运行 dup 程序:
bash
#!/bin/bash
# 方法1: 直接输入文本,按Ctrl+D结束输入
echo "=== 方法1: 直接输入文本 ==="
echo "运行程序后,输入几行文本,然后按Ctrl+D结束输入"
echo "例如:"
echo "hello"
echo "world"
echo "hello"
echo "然后按Ctrl+D"
# 方法2: 通过管道从文件读取
echo -e "\n=== 方法2: 通过管道从文件读取 ==="
echo "cat sample.txt | go run ch01/dup/main.go"
echo "输出结果:"
cat sample.txt | go run ch01/dup/main.go
# 方法3: 通过重定向输入
echo -e "\n=== 方法3: 通过重定向输入 ==="
echo "go run ch01/dup/main.go < sample.txt"
echo "输出结果:"
go run ch01/dup/main.go < sample.txtsample.txt
text
hello
world
hello
go
programming
world
hello