读《Go语言圣经》记录(一)

读《Go语言圣经》记录(一)

在编程语言的海洋中,Go语言以其简洁的语法、高效的并发处理能力和强大的标准库迅速崭露头角,成为开发者的宠儿。本文将带大家深入探索《Go语言圣经》的入门章节,并结合实际示例和扩展知识,开启一段精彩的Go语言学习之旅。

第一章:入门

1.1 Hello, World

每个编程之旅都从"Hello, World"开始。在Go语言中,编写一个简单的"Hello, World"程序易如反掌。以下是代码示例:

go 复制代码
package main

import "fmt"

func main() {
    fmt.Println("Hello, 世界")
}

这段代码展示了Go语言的基本结构:package main声明了程序的入口包,import "fmt"引入了格式化I/O包,func main()是程序的入口函数,而fmt.Println则用于输出文本。运行这段代码,你将在控制台看到"Hello, 世界"的友好问候。

1.2 命令行参数

Go语言通过os包提供对命令行参数的访问。以下是一个示例,展示如何读取并处理命令行参数:

go 复制代码
package main

import (
    "fmt"
    "os"
)

func main() {
    args := os.Args
    for i, arg := range args {
        fmt.Printf("Argument %d: %s\n", i, arg)
    }
}

将此代码保存为args.go,然后通过命令行运行go run args.go arg1 arg2,你将看到程序输出传递给它的参数。

1.3 查找重复的行

处理文本数据是编程中的常见任务。下面是一个程序,用于查找输入中的重复行:

go 复制代码
package main

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

func main() {
    counts := make(map[string]int)
    input := bufio.NewScanner(os.Stdin)
    for input.Scan() {
        line := input.Text()
        counts[line]++
    }
    for line, count := range counts {
        if count > 1 {
            fmt.Printf("%d\t%s\n", count, line)
        }
    }
}

将此代码保存为dups.go,然后通过管道传递文本文件内容,如cat file.txt | go run dups.go,程序将输出文件中重复的行及其出现次数。

1.4 GIF动画

Go的imagegif包使得创建图像和动画变得简单。以下是一个生成GIF动画的示例:

go 复制代码
package main

import (
    "image"
    "image/color"
    "image/gif"
    "math"
    "os"
)

func main() {
    const (
        cycles  = 5
        res     = 0.001
        size    = 100
        nframes = 64
        delay   = 8
    )
    anim := gif.GIF{LoopCount: nframes}
    palette := []color.Color{color.White, color.Black}
    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*1.5)
            img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), 1)
        }
        anim.Delay = append(anim.Delay, delay)
        anim.Image = append(anim.Image, img)
    }
    gif.EncodeAll(os.Stdout, &anim)
}

运行此程序并将输出重定向到GIF文件,如go run lissajous.go > out.gif,你将得到一个美丽的GIF动画。

1.5 获取URL

Go的net/http包提供了强大的HTTP客户端功能。以下是如何获取网页内容的示例:

go 复制代码
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
)

func main() {
    resp, err := http.Get("https://example.com")
    if err != nil {
        fmt.Fprintf(os.Stderr, "fetch: %v\n", err)
        os.Exit(1)
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", resp.Request.URL, err)
        os.Exit(1)
    }
    fmt.Printf("%s", body)
}

将此代码保存为fetch.go并运行go run fetch.go https://example.com,你将在控制台看到网页的HTML内容。

1.6 并发获取多个URL

Go的并发模型是其最大的亮点之一。通过goroutines和channels,可以轻松地并发获取多个URL:

go 复制代码
package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

func main() {
    start := time.Now()
    ch := make(chan string)
    for _, url := range os.Args[1:] {
        go fetch(url, ch)
    }
    for range os.Args[1:] {
        fmt.Println(<-ch)
    }
    fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds())
}

func fetch(url string, ch chan<- string) {
    start := time.Now()
    resp, err := http.Get(url)
    if err != nil {
        ch <- fmt.Sprintf("error: fetching %s: %v", url, err)
        return
    }
    defer resp.Body.Close()
    nbytes, err := io.Copy(io.Discard, resp.Body)
    if err != nil {
        ch <- fmt.Sprintf("error: reading %s: %v", url, err)
        return
    }
    secs := time.Since(start).Seconds()
    ch <- fmt.Sprintf("%.2fs  %7d  %s", secs, nbytes, url)
}

运行此程序并传递多个URL作为参数,你将看到每个URL的获取时间和数据大小。

1.7 Web服务

创建一个简单的Web服务器来响应HTTP请求:

go 复制代码
package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe("localhost:8000", nil)
}

运行此程序并在浏览器中访问http://localhost:8000,你将看到请求的URL路径。

1.8 本章要点

本章涵盖了Go语言的基础知识,包括如何编写和运行程序、处理命令行参数、文本处理、图像生成、网络编程和并发编程。通过这些示例,我们不仅学习了Go语言的语法,还了解了其强大的标准库和并发模型。

扩展知识与最佳实践

错误处理

在处理外部操作(如文件I/O或网络请求)时,总是检查错误并进行适当的处理:

go 复制代码
resp, err := http.Get(url)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

使用defer确保资源被正确释放。

并发模式

Go的并发模型基于CSP(Communicating Sequential Processes)。使用goroutineschannels来协调并发任务:

go 复制代码
ch := make(chan int)
go func() {
    for i := 0; i < 3; i++ {
        ch <- i
    }
    close(ch)
}()
for num := range ch {
    fmt.Println(num)
}

性能优化

使用sync.Pool来重用对象,减少内存分配和垃圾回收的开销:

go 复制代码
var pool = sync.Pool{
    New: func() interface{} {
        return make([]byte, 1024)
    },
}

func getBuffer() []byte {
    return pool.Get().([]byte)
}

func putBuffer(b []byte) {
    pool.Put(b)
}
相关推荐
菥菥爱嘻嘻40 分钟前
JS手写代码篇---Pomise.race
开发语言·前端·javascript
南瓜胖胖1 小时前
【R语言编程绘图-调色】
开发语言·r语言
lanbing2 小时前
非常适合初学者的Golang教程
开发语言·后端·golang
stormsha3 小时前
GO语言进阶:掌握进程OS操作与高效编码数据转换
开发语言·数据库·后端·golang·go语言·源代码管理
B1nna3 小时前
SpringBoot项目快速打包与部署,War包⽅式打包部署与Jar包⽅式打包部署两种方式
spring boot·后端·jar
老神在在0014 小时前
javaEE1
java·开发语言·学习·java-ee
魔道不误砍柴功4 小时前
《接口和抽象类到底怎么选?设计原则与经典误区解析》
java·开发语言
我是李武涯5 小时前
C++ 条件变量虚假唤醒问题的解决
开发语言·c++·算法
编码小笨猪5 小时前
[ Qt ] | 常用控件(三):
开发语言·qt
Bioinfo Guy5 小时前
R包安装报错解决案例系列|R包使用及ARM架构解决data.table安装错误问题
开发语言·arm开发·r语言