《go语言入门与精通》实操笔记

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.gif
package 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)
    }
}

标签: go语言

移动端可扫我直达哦~

推荐阅读

thumbnail 2026-06-04

go语言gin框架的学习笔记

上半年尝试制作了一个微信小程序,通过小程序请求后台服务器,服务器负责组装好用户需求的mp3文件,然后返回给用户播放地址,以实现一个简单的听写功能。其中后台的逻辑基本都是通过deepseek实现的,虽然成功跑通了,但是一直想从头手搓一遍...

少儿编程 go语言

thumbnail 2026-06-02

提升读写性能,go语言的bufio包

最近在尝试学习go语言,想去洛谷做几道题吧,结果前几个答案是正确的,最后两个报了超时,标准输入输出fmt存在读写性能上的缺陷。deepseek推荐了这个bufio包。bufio 包的核心功能bufio 提供缓冲 I/O,通过减少系统调...

少儿编程 go语言

thumbnail 2026-05-30

fmt,Go 语言自带的格式化输入输出包

fmt 可以理解为 Format(格式)的缩写——因为它擅长格式化数据(比如把数字嵌进句子中间)。fmt 就是 Go 语言的"终端对话工具",让你能在屏幕上显示东西,也能从键盘获取输入。fmt包的常用指令 概念对应 fmt 函数标准输...

少儿编程 go语言

thumbnail 2026-05-27

乱点技能树之-go语言笔记篇

系统仍旧是廉颇老矣的windows7,所以很多软件的新版本都没法运行,就像go已经出到了1.26版本,但win7上仅支持1.20.14,再往上就不受支持了,所以下方的代表仅在上述版本中验证通过。学习go语言的第一感受是,go语言取消了...

少儿编程 go语言