基本介绍
可以参考此文章:https://docs.hacknode.org/gopl-zh/ch0/ch0-02.html
基础使用
查看go版本
go version
引入代码
需要在环境变量中添加GOPATH目录,然后使用go get 命令下载代码,以下为《go语言圣经》的示例
export GOPATH=$HOME/go # 选择工作目录
go get gopl.io/ch1/helloworld # 获取/编译/安装
$GOPATH/bin/helloworld # 运行程序
执行代码
执行代码使用go run命令
go run hello.go
编译代码
编译代码使用go build命令,执行完后会生成一个可执行文件,在windows会生成一个exe文件
go build hello.go
main包和main函数的特殊性
main包比较特殊。它定义了一个独立可执行的程序,而不是一个库。
在main里的main 函数 也很特殊,它是整个程序执行时的入口(译注:C系语言差不多都这样)。
main函数所做的事情就是程序做的。当然了,main函数一般调用其它包里的函数完成很多工作, 比如, fmt.Println。
代码示例
可以直接参考(2)go基础学习-基本使用
命令行参数
在文档中给出的示例是:
package main
import (
"fmt"
"os" //os包以跨平台的方式,提供了一些与操作系统交互的函数和变量。程序的命令行参数可从os包的Args变量获取;os包外部使用os.Args访问该变量。
)
func main() {
var s, sep string
for i := 0; i < len(os.Args); i++ {
s += sep + os.Args[i]
sep = " " //添加空格属于二次加工,参数数量庞大时开销很大
}
fmt.Println(s)
}
对于string类型,+表示连接字符串(与js和C++语法相同)
for循环
for循环有多种形式
for initialization; condition; post {
// zero or more statements
}
// a traditional "while" loop
for condition {
// ...
}
// a traditional infinite loop,可以通过break或return终止循环
for {
// ...
}
for循环在range中遍历,修改以上示例为:
package main
import (
"fmt"
"os"
)
func main() {
var ret, sep string
for _, arg := range os.Args[1:] {
ret += sep + arg
sep = " "
}
fmt.Println(ret)
}
使用循环来拼接字符串代价高昂,一种简单且高效的解决方案是使用strings包的Join函数
package main
import (
"fmt"
"os"
"strings"
)
func main() {
fmt.Println(strings.Join(os.Args[1:], " "))
}
如果不关心输出格式,可以直接输出:
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println(os.Args[1:])
}
练习题
练习1.2
修改echo程序,使其打印每个参数的索引和值,每个一行。
package main
import (
"fmt"
"os"
)
func main() {
for key, val := range(os.Args[1:]) {
fmt.Println(key)
fmt.Println(val)
}
}
练习1.3
做实验测量潜在低效的版本和使用了strings.Join的版本的运行时间差异。(1.6节讲解了部分time包,11.4节展示了如何写标准测试程序,以得到系统性的性能评测。)
简单实现
package main
import (
"fmt"
"os"
"strings"
"time"
)
func main() {
firstStart := time.Now().Nanosecond()
var s1, sep string
for i := 1; i < len(os.Args); i++ {
s1 += sep + os.Args[i]
sep = " "
}
fmt.Println(s1)
firstEnd := time.Now().Nanosecond()
timeSpace := firstEnd - firstStart
fmt.Println("%.2fs long time space: ", timeSpace)
secondStart := time.Now().Nanosecond()
fmt.Println(strings.Join(os.Args[1:], " "))
secondEnd := time.Now().Nanosecond()
timeSpace2 := secondEnd - secondStart
fmt.Println("%.2fs short time space: ", timeSpace2)
}
加上测试
todo… #查找重复的行
从标准输入中读入数据
可以对重复行计数,从标准输入中读入数据,输入ctrl+D结束并运行
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
counts := make(map[string]int) //map[key][val]
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
counts[input.Text()]++
}
for k, v := range counts {
if v > 1 {
fmt.Println("val %s key %d", k, v)
}
}
}
从文件中读入数据
读取标准输入或是使用os.Open打开各个具名文件,并操作它们
/**
1 获取所有参数,若未获取到,直接获取输入内容进行比较
2 获取到了则打开文件
3 获取行数
*/
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
counts := make(map[string]int)
files := os.Args[1:]
if len(files) < 1 {
compareByMap(os.Stdin, counts)
} else {
for _, args := range files {
f, err := os.Open(args)
if err != nil {
fmt.Fprintf(os.Stderr,"err is: %v", err) //任意类型默认格式值的动词%v
continue
}
f.Close()
compareByMap(f, counts)
}
}
for key, val := range counts {
if val > 1 {
fmt.Printf("名称:%s出现了%d次\n", key, val)
}
}
}
func compareByMap(f *os.File, counts map[string]int) {
input := bufio.NewScanner(f)
for input.Scan() {
counts[input.Text()]++
}
}
一次性读取文件全部数据
/**
1 只读文件,不读标准输入
2 读取文件内容,并做错误处理
3 \n切割文件内容并放入map中
4 出现次数大于1则输出
*/
package main
import (
"fmt"
"io/ioutil"
"os"
"strings"
)
func main() {
counts := make(map[string]int)
files := os.Args[1:]
for _, arg := range files {
file, err := ioutil.ReadFile(arg) //ReadFile函数返回一个字节切片
if err != nil {
fmt.Fprintf(os.Stderr, "error:%v\n", err)
continue
}
for _, line := range strings.Split(string(file), "\n") {
counts[line]++
}
}
for key, val := range counts {
if val > 1 {
fmt.Printf("参数%s出现了%d次\n", key, val)
}
}
}