Go语言高级编程

https://chai2010.cn/advanced-go-programming-book/

为什么学习 golang

golang 的创始人: Rob Pike(罗伯。 派克),Ken Thompson(肯。 汤普森)和 Robert Griesemer(罗伯特。 格利茨默)。

  • Rob Pike:曾是贝尔实验室(Bell Labs)的 Unix 团队,和 Plan 9 操作系统计划的成员。他与 Thompson 共事多年,并共创出广泛使用的 UTF-8 字元编码。
  • Ken Thompson:主要是 B 语言、C 语言的作者、Unix 之父。1983 年图灵奖(Turing Award)和 1998 年美国国家技术奖(National Medal of Technology)得主。他与 Dennis Ritchie 是 Unix 的原创者。Thompson 也发明了后来衍生出 C 语言的 B 程序语言。
  • Robert Griesemer:在开发 Go 之前是 Google V8、Chubby 和 HotSpot JVM 的主要贡献者。
  • 此外还有 Plan 9 开发者 Russ Cox、和曾改善目前广泛使用之开原码编译器 GCC 的 Ian Taylor。

可以将 golang 看作进化版的 c 语言

python 是开发效率和表现力很强的语言, 唯一的缺点在于脚本语言与生俱来的效率。

可以用 C 扩展提速 python, 但是开发效率低。golang 刚刚好。

谨慎开始学习一门新语言, 在 python 自身优化 (包括使用必要的库) 足够的情况下, 没必要学习 golang.

第 1 章 语言基础

我不知道,你过去 10 年为什么不快乐。但相信我,抛掉过去的沉重,使用 Go 语言,体会最初的快乐!——469856321

Go 语言终于完成了从单机单核时代的 C 语言到 21 世纪互联网时代多核环境的通用编程语言的蜕变。

Go 语言最初由 Google 公司的 Robert Griesemer、Ken Thompson 和 Rob Pike 三个大牛于 2007 年开始设计发明,设计新语言的最初的洪荒之力来自于对超级复杂的 C ++11 特性的吹捧报告的鄙视,最终的目标是设计网络和多核时代的 C 语言。

源文件采用 UTF8 编码是 Go 语言规范所要求的

简单是重要的原则, 于技术, 于生活都是。

  • 所有的 Go 程序,都是由最基本的函数和变量构成
    • 函数和变量被组织到一个个单独的 Go 源文件中
      • 这些源文件再按照作者的意图组织成合适的 package
        • 最终这些 package 再有机地组成一个完整的 Go 语言程序。
          - main 包中的 main 函数默认是每一个可执行程序的入口

fmt 是 format 单词的缩写,表示格式化相关的包

Go 语言中的字符串内容是不可变更的。 这和 Python 是相同的。

在 Go 语言中,函数参数都是以复制的方式 (不支持以引用的方式) 传递, 这和 Python 是不同的。

Go 语言采用是否大小写首字母来区分符号是否可以被导出:大写字母开头表示导出的公共符号,小写字母开头表示包内部的私有符号。

你好, 世界!

helloworld.og

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
)

func main() {
// net/http 包构造了一个独立运行的 http 服务
// http.HandleFunc("/", ……)针对 / 根路径请求注册了响应处理函数
// 在响应处理函数中,使用 fmt.Fprintf 格式化输出函数实现了通过 http 协议向请求的客户端打印格式化的字符串
//     同时通过标准库的日志包在服务器端也打印相关字符串。// 最后通过 http.ListenAndServe 函数调用来启动 http 服务。fmt.Println("Please visit http://127.0.0.1:12345/")
    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {s := fmt.Sprintf(" 你好, 世界! -- Time: %s", time.Now().String())
        fmt.Fprintf(w, "%v\n", s)
        log.Printf("%v\n", s)
    })

    if err := http.ListenAndServe(":12345", nil); err != nil {log.Fatal("ListenAndServe: ", err)
    }
}

以脚本方式运行:

go run helloworld.go

编译并以 exe 方式运行:

go build helloworld.go
helloworld.exe

数组、字符串和切片

在主流的编程语言中数组及其相关的数据结构是使用得最为频繁的,只有在它 (们) 不能满足时才会考虑链表、hash 表(hash 表可以看作是数组和链表的混合体)和更复杂的自定义数据结构。

Go 语言中数组、字符串和切片三者是密切相关的数据结构。这三种数据类型,在底层原始数据有着相同的内存结构,在上层,因为语法的限制而有着不同的行为表现。

  • 首先,Go 语言的数组是一种值类型,虽然数组的元素可以被修改,但是数组本身的赋值和函数传参都是以整体复制的方式处理的。
  • Go 语言字符串底层数据也是对应的字节数组,但是字符串的只读属性禁止了在程序中对底层字节数组的元素的修改。字符串赋值只是复制了数据地址和对应的长度,而不会导致底层数据的复制。
  • 切片的行为更为灵活,切片的结构和字符串结构类似,但是解除了只读限制。切片的底层数据虽然也是对应数据类型的数组,但是每个切片还有独立的长度和容量信息,切片赋值和函数传参数时也是将切片头信息部分按传值方式处理。因为切片头含有底层数据的指针,所以它的赋值也不会导致底层数据的复制。其实 Go 语言的赋值和函数传参规则很简单,除了闭包函数以引用的方式对外部变量访问之外,其它赋值和函数传参数都是以传值的方式处理。

要理解数组、字符串和切片三种不同的处理方式的原因需要详细了解它们的底层数据结构。

数组

数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。

数组的长度是数组类型的组成部分。

因为数组的长度是数组类型的一个部分,不同长度或不同类型的数据组成的数组都是不同的类型,因此在 Go 语言中很少直接使用数组(不同长度的数组因为类型不同无法直接赋值)。

和数组对应的类型是切片,切片是可以动态增长和收缩的序列,切片的功能也更加灵活,但是要理解切片的工作原理还是要先理解数组。

评论(没有评论)