Hello,World!
无可争议的 hello,world! 展示了go语言导入包以及打印的过程,学过一段时间c++,感觉go的语法是在给c++做减法。
package main
import "fmt"
func main() {
fmt.Println("Hello,world!")
}os包
书里的第二个实例就涉及到了os包,难度跨度感觉还是挺大的,Go语言的 os 包提供了操作系统功能的跨平台接口,让程序能够与操作系统进行交互,包括:
- 文件与目录操作
- 环境变量管理
- 进程控制
- 命令行参数获取
- 标准输入/输出/错误流
package main
import (
"fmt"
"os"
)
func main() {
var s, sep string
for i := 1; i < len(os.Args); i++ {
s += sep + os.Args[i]
sep = " "
}
fmt.Println(s)
}os.Args的第一个元素os.Args[0]是命令本身的名字;其它的元素则是程序启动时传给它的参数。这个案例直接编译运行的时候是看不到任何输出的,需要运行时传入参数才会有输出,巧妇难为无米之炊么,参考的测试命令如下:
go run . aa bb cc遍历
上一个案例使用了循环操作,go里面的循环统一用for,没有了while以及do...while,刚学c++的时候就挺困惑,一个循环为什么要有这么多种写法,很多年后go语言回复:确实没必要。遍历如同其字面意思,就是把一个集合里的所以对象都过一遍,同循环不同的是,循环提供一个上下限,而遍历则需要给它一个可遍历的集。
package main
import (
"fmt"
"os"
)
func main() {
var s, sep string
for _, arg := range os.Args[1:] {
s += sep + arg
sep = " "
}
fmt.Println(s)
}查找重复的文本行
这个案例里出现一个新包 bufio,bufio (buffered I/O) 包提供了带缓冲区的读写操作,通过在内存中维护缓冲区来减少直接的系统调用次数,从而大幅提升 I/O 性能。这个在洛谷刷题的时候可能经常需要用到,遇到数据较多的情况,用fmt包容易产生超时。这个案例在命令行测试时,需要先按行输入内容,输入结束按ctrl+z查看结果。程序会统计用户输入的内容中是否有重复的行。
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
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)
}
}
}手动输入有点累人,也可以把内容写入在文件中,让程序去读取文件并统计文件内的重复行,下面这个程序通过一个判断,同时支持了这两种方式的内容输入:
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()]++
}
}通过在运行命令后提供文件名,就可以实现统计效果。
go run . input.txt生成一个gif图片
暂时跳过的一个实例,看不懂,利用如下命令可以输出图片到本地:
go run . >test.gifpackage main
import (
"image"
"image/color"
"image/gif"
"io"
"math"
"math/rand"
"os"
)
var palette = []color.Color{color.White, color.Black}
const (
whiteIndex = 0 // first color in palette
blackIndex = 1 // next color in palette
)
func main() {
lissajous(os.Stdout)
}
func lissajous(out io.Writer) {
const (
cycles = 5 // number of complete x oscillator revolutions
res = 0.001 // angular resolution
size = 100 // image canvas covers [-size..+size]
nframes = 64 // number of animation frames
delay = 8 // delay between frames in 10ms units
)
freq := rand.Float64() * 3.0 // relative frequency of y oscillator
anim := gif.GIF{LoopCount: nframes}
phase := 0.0 // phase difference
for i := 0; i < nframes; i++ {
rect := image.Rect(0, 0, 2*size+1, 2*size+1)
img := image.NewPaletted(rect, palette)
for t := 0.0; t < cycles*2*math.Pi; t += res {
x := math.Sin(t)
y := math.Sin(t*freq+phase)
img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5),
blackIndex)
}
phase += 0.1
anim.Delay = append(anim.Delay, delay)
anim.Image = append(anim.Image, img)
}
gif.EncodeAll(out, &anim) // NOTE: ignoring encoding errors
}获取url
获取对应网络地址的内容,学习go语言的初心是想用go为博主的小鸟听写小程序实现后端服务,原来是用的python。因为io/ioutil这个包在go1.16之后已不推荐使用,所以对程序进行了小幅修改:
- 移除:"io/ioutil" 导入
- 添加:"io" 导入
- 替换:ioutil.ReadAll() → io.ReadAll()
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
for _, url := range os.Args[1:] {
resp, err := http.Get(url)
if err != nil {
fmt.Fprintf(os.Stderr, "fetch: %v\n", err)
os.Exit(1)
}
b, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err)
os.Exit(1)
}
fmt.Printf("%s", b)
}
}忽略错误处理后的整体流程:
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
for _, url := range os.Args[1:] {
res, _ := http.Get(url)
b, _ := io.ReadAll(res.Body)
res.Body.Close()
fmt.Printf("%s", b)
}
}

