关于go:GOGO-HANDBOOK读书笔记

47次阅读

共计 10232 个字符,预计需要花费 26 分钟才能阅读完成。

Go

引言

十分入门的一本书?精确来说是一篇 GO 的入门文章,用于学学英语和简略理解 GO 还不错,并且词汇和语法都比拟简洁易懂。

话不多说,上面就来看看这篇文章的翻译。

原文

https://www.freecodecamp.org/news/go-beginners-handbook/

1. 介绍 GO

它是由谷歌工程师创立的,设计这门语言的次要指标是:

  • 进步我的项目的编译和运行速度
  • 入门门槛足够低,然而也要防止过于简略和低级。
  • 具备可移植(编译后的 Go 程序是二进制文件,不须要其余文件就能运行,而且是跨平台的,因而能够很容易地散发)
  • 枯燥、稳固、可预测,犯错的机会少。
  • 能充分发挥多线程劣势

2. 如何开始?

在深刻理解该语言的具体内容之前,您应该理解以下几件事。

首先,https://go.dev 是该语言的主页。

上面是首选的入门资源:

  • 从 https://go.dev/doc/install 下载 Go 二进制文件(go 命令和其余相干工具)。
  • 参考 Go 官网文档:https://go.dev/doc/
  • 查看所有 Go 软件包:https://pkg.go.dev/
  • 拜访 Go Playground:https://go.dev/play/

3. 装置 GO

装置 GO 的教程网上一抓一大把,集体应用的是 Window 环境,Windows 环境下只须要装置 exe 应用程序即可,简略无脑就不演示了。

4. 开发 IDE 装置和配置

NOTE: you might have to open a new terminal before you can run the program, as the installer added the Go binaries folder to the path.

留神:因为安装程序在门路中增加了 Go 二进制文件夹,运行程序前可能须要关上一个新的终端。

在应用 IDE 之前,请先确保本人的环境变量能够失常应用 GO。

本书应用的是 VS Code,具体能够浏览此网站理解:Go with Visual Studio Code。

[[【Go】Go in Visual Studio Code]]

VS Code 装置之后,须要装置 GO 相干的扩大:marketplace.visualstudio.com/items?itemName=golang.go

5. 你好,世界

  1. 创立一个新的文件夹,比方上面的 hello。
  1. 创立一个 hello.go 的文件,并且在文件内写入上面的内容:
package main 

import "fmt" 

func main() {fmt.Println("Hello, World!") 
}
  1. 在文件所在门路,运行go run hello.go,如果后果如下阐明运行胜利:
xander@LAPTOP-47J243NL MINGW64 /e/adongstack/go/hello

$ go run hello.go
 Hello, World!

上面来解释下下面的入门程序:

  1. 每个 .go 文件首先申明它是哪个软件包的一部分
  2. 一个软件包能够由多个文件组成,也能够只由一个文件组成。一个程序能够蕴含多个软件包。
  3. main函数是程序的入口点,也是可执行程序的标识。
  4. 咱们应用 import 关键字来导入程序包。

fmt is a built-in package provided by Go that provides input/ output utility functions.

fmt 是 Go 提供的一个内置包,提供输出 / 输入实用功能。

GO 官网领有宏大的规范库,从网络连接到数学、明码、图像处理、文件系统拜访等,咱们都能够应用它。

Standard library – Go Packages

比方,无关fmt 这个包的文档介绍能够查看这个地址理解:fmt package – fmt – Go Packages,依据文档,该函数性能是 “ 依据格局说明符进行格式化,并写入规范输入 ”。

咱们应用 “ 点 “ 语法 fmt.Println()来指定该函数由该程序包提供。

当代码执行完主函数后,就没有其余事件可做了,执行完结。

在 main 函数中,咱们定义了 fmt.Println("Hello, World!") 这样一串代码。

6. 编译并运行 Go 程序

本局部接着上一章节的入门程序介绍,解释如何编译并且运行 go 程序

go run hello.go

go run 工具首先编译,而后运行指定的程序。

咱们能够应用 go build 创立二进制文件:

go build hello.go

个人电脑上执行的后果如下:

PS E:\adongstack\go\hello> go build .\hello.go
PS E:\adongstack\go\hello> dir


    目录: E:\adongstack\go\hello


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         2023/9/19     13:33        1897472 hello.exe
-a----         2023/9/19     13:32             84 hello.go

Go 是可移植的,因为实质编译之后实质就是二进制文件,这样每个人都能够按原样运行程序,并且二进制文件曾经打包供执行。

程序将在咱们构建它的雷同架构上运行。

咱们能够应用 GOOSGOARCH 环境变量为不同的架构创立不同的二进制文件:

GOOS = windows GOARCH = amd64 go build hello.go

这将为 64 位 Windows 机器创立一个 hello.exe 可执行文件:

64 位 macOS(英特尔或苹果)的设置为

GOOS = darwin GOARCH = amd64

Linux 为 :

GOOS = linux GOARCH = amd64

这是 Go 的最佳性能之一。

7. 工作空间

Go 有一个特别之处就是咱们所说的工作空间。

工作区是 Go 的 “ 大本营 ”。

默认状况下,Go 会抉择 $ HOME/ go 门路,因而你会在主目录中看到一个 go 文件夹。

例如,当我在 VS Code 中加载 hello.go 文件时,它提醒我装置 gopls 命令、Delve 调试器 (dlv) 和 staticcheck linter。

它们已主动装置在 $ HOME/ go 下:

当你应用 go install 装置软件包时,它们将被存储在这里。

这就是咱们所说的 GOPATH。

你能够更改 GOPATH 环境变量来扭转 Go 安装包的地位。

当你同时在不同的我的项目中工作,并心愿隔离你应用的库时,这一点十分有用。

8. 深刻语言

既然咱们曾经有了初步的概念,并运行了第一个 Hello, World! 程序,那么咱们就能够深入研究这门语言了。

这种语言没有语义上重要的空白。

就像 C、C + +、Rust、Java 和 JavaScript。与 Python 不同的是,Python 的空白是有意义的,它被用来创立块而不是大括号。

Go 非常重视 缩进和视觉程序。装置 Go 时,咱们还能够应用 gofmt 命令行工具来格式化 Go 程序。

VS Code 在引擎盖下应用该工具来格式化 Go 源文件。

这是一个十分有意思的个性,语言创建者定义了规定,每个人都会应用这些规定。

这非常适合大型团队的我的项目。

本书倡议在 VS Code 当中设置“Format on Save”以及“Format on Paste”:

Go 中的正文应用常见的 C / C + + / JavaScript / Java 语法:

9. 变量

在 GO 外面能够是用 var关键字定义变量:

var age = 20

var 关键字能够定义包级别变量:

package main 

import "fmt" 

var age = 20 

func main() {fmt.Println("Hello, World!") 
}

或者定义在函数外部:

package main 

import "fmt" 



func main() { 

    var age = 20 
    
    fmt.Println("Hello, World!") 
}

在软件包级别定义的变量在组成软件包的所有文件中都是可见的。

一个软件包能够由多个文件组成,只需创立另一个文件,并在顶部应用雷同的软件包名称即可。

在函数外部定义的变量,一个变量只能在函数中可见。

这使得 Go 判断变量 age 的类型是 int。

咱们稍后会看到更多对于类型的内容,但你应该晓得有许多不同的类型,首先是 int、string 和 bool。

咱们也能够申明一个没有现存值的变量,但在这种状况下,咱们必须像这样设置类型:

var age int 
var name string 
var done bool

当您晓得变量值时,通常应用带有 := 操作符的短变量申明:

age := 10 
name := "Roger"

留神变量名称是辨别大小写的,如果名称较长,通常应用 驼峰字母大写,因而咱们应用 carName 来示意汽车的名称。

您能够应用赋值运算符 = 为变量赋值。

var age int 
age = 10 
age = 11

如果一个变量确定不会扭转,能够应用 const 关键字定义:

const age = 10

你能够在一行定义多个变量:

var age, name = 10, "Roger" 

// or 

age, name := 10, "Roger"

如果定义了变量然而没有应用,在 VS Code 中会有相干提醒。

这些错误信息理论是编译

如果您申明一个变量,但没有将其初始化为一个值,那么它会主动调配一个值,这个值取决于变量的类型,例如整数为 0,字符串为空字符串。

10. 根本类型

Go 的根本类型有

  • 整数(int、int8、int16、int32、rune、int64、uint、uintptr、uint8、uint16、uint64)
  • 浮点数(float32、float64),用于示意小数
  • 复数类型(complex64、complex128),用于数学运算
  • 字节(byte),示意单个 ASCII 字符
  • 字符串(string),一组字节
  • 布尔类型(bool),示意真或假

咱们有很多不同的类型来示意 interger,大部分工夫你都会应用 int,你可能会抉择一个更业余的类型来进行优化(刚开始学习时不须要思考这些)。

int 类型针对 32 位机器和 64 位的机器做了类型适配,

uint 是一个无符号的 int,如果晓得数值不会是正数,就能够用它来加倍存储数值。

11. 字符串

Strings 在 Go 语言中是一串字节数组。

咱们能够应用上面的语法定义一串字符串:

var name = "test"

值得注意的是,与其余语言不同,字符串的定义只能应用双引号,而不能应用单引号(比方 JS)。

能够应用len 函数获取字符串长度

len(name) // 4

您能够应用方括号拜访单个字符,同时传递您要获取的字符的索引:

name[0] //"t" (indexes start at 0) 
name[1] //"e"

能够应用上面的语法像 Python 语言一样对于字符串进行“切片”:

name[0: 2] //"te" 
name[: 2] //"te" 
name[2:] //"st"

应用上面的语法能够拷贝一个字符串:

var newstring = name[:]

您能够将一个字符串赋值给一个新变量:

var first = "test" 
var second = first

Strings 是不可变变量,意味着你不能更新一个 Strings,即便应用赋值运算符为第一项赋值,第二项的值依然是 “test”:

var first = "test" 

var second = first 

first = "another test" 

first //"another test" 
second //"test"

字符串是 援用类型 ,这意味着如果将字符串传递给函数,复制的将是 字符串的援用,而不是其值。

但因为字符串是不可变的,在这种状况下,与传递 int 等类型的字符串在实际操作中并无太大区别。

能够应用 + 运算符连贯两个字符串:

var first = "first" 

var second = "second" 

var word = first + "" + second //" first second"

Go 在字符串包中提供了多个字符串实用程序。

咱们曾经在 “Hello, World!” 示例中看到了如何导入包,上面介绍如何导入字符串:

以下是导入字符串的办法:

package main 

import ("strings")

12. 数组

数组是由繁多类型的我的项目组成的序列。

咱们这样定义一个数组:

var myArray [3] string // 蕴含 3 个字符串的数组

你能够应用以下值初始化数组:

var myArray = [3] string{"First", "Second", "Third"}

在这种状况下,你也能够让 Go 来帮你计数:

var myArray = [...] string{"First", "Second", "Third"} 

留神,数组只能蕴含雷同类型的值。

数组不能调整大小,必须在 Go 中明确定义数组的长度。

数组不能调整大小,必须在 Go 中明确定义数组的长度。

这是数组类型的一部分。此外,也不能应用变量来设置数组的长度。

因为这种限度,在 Go 中很少间接应用数组,而是应用 Slice(稍后会具体介绍)。

留神 Slice 底层也是数组实现的,所以理解数组是根底。

数组能够通过方括号加下标值获取数组特定地位,而后针对特定地位设置新值。

myArray[0] // indexes start at 0 

myArray[1]

数组也能够应用len() 函数获取数组长度:

数组是 值类型。这意味着能够复制数组:

anotherArray := myArray

将数组传递给函数,或从函数中返回数组,都会 创立原始数组的正本

这与其余编程语言不同。

让咱们举一个简略的例子,在复制一个数组项后,给它赋一个新值。

请看,拷贝并没有扭转:

var myArray = [3] string{"First", "Second", "Third"} 

myArrayCopy := myArray 

myArray[2] = "Another" 

myArray[2] //"Another"
myArrayCopy[2] //"Third"

请记住,你只能在数组中增加繁多类型的项,因而设置 myArray[2] = 2 会引发谬误。

底层元素在内存中间断存储。

低级元素继续存储在内存中。

13. 分片

分片是一种相似于数组的数据结构,但它的大小能够扭转。

切片应用数组,是建设在数组之上的一种形象构造,它使切片更灵便、更有用(将数组视为低级构造)。

如果你晓得须要对切片执行操作,你能够要求它领有比最后须要的更大容量,这样当你须要更多空间时,空间就会随时可用(而不是找到切片并将其挪动到一个有更多空间的新内存地位,而后通过垃圾回收解决旧地位)。

咱们能够为 make() 增加第三个参数来指定容量:

newSlice := make([] string, 0, 10) // an empty slice with capacity 10

多个切片能够应用同一个数组作为底层数组:

myArray := [3] string{"First", "Second", "Third"} mySlice = myArray[:]

与字符串一样,应用该语法能够获取片段的一部分:

mySlice := [] string{"First", "Second", "Third"} newSlice := mySlice[: 2] // get the first 2 items newSlice2 := mySlice[2:] // ignore the first 2 items newSlice3 := mySlice[1: 3] // new slice with items in position 1-2

14.Maps

map 是 go 语言的罕用数据类型。

agesMap := make(map[ string] int)

您无需设置地图可包容的物品数量。您能够通过这种形式向 map 增加新内容:

agesMap["flavio"] = 39

您也能够应用以下语法间接用值初始化映射:

agesMap := map[string] int{"flavio": 39}

通过上面的语法能够获取 map 的 key 的值:

age := agesMap["flavio"]

应用delete() 函数能够删除 Map 中对应的 Key。

delete(agesMap, "flavio")

15. 循环

Go 的循环语句关键字也是for:

for i := 0; i < 10; i + + {fmt.Println( i) 
}

咱们首先初始化一个循环变量,而后设置每次迭代时要查看的条件,以决定循环是否应该完结,最初在每次迭代完结时执行 post 语句,在本例中,该语句会递增 i。

i++ 使 i 变量递增。

< 操作符用于将 i 与数字 10 进行比拟,并返回 true 或 false,以决定是否执行循环体。

与 C 或 JavaScript 等其余语言不同,咱们不须要在该代码块四周应用括号。

此外还须要留神,Go 没有 while这样的循环语法,如果想要实现相似的性能,能够应用 for 进行模仿。

i := 0 for i < 10 {fmt.Println( i) i + + 
    
}

此外能够通过 break 语句跳出循环。

for {fmt.Println( i) 
     
     if i < 10 {break} 
     i ++ 
}

我在循环体中应用了 if 语句,但咱们还没有看到条件!咱们下一步再做。

当初我要介绍的是范畴。

咱们能够应用 for 语法遍历数组:

numbers := [] int{ 1, 2, 3} 

for i, num := range numbers {fmt.Printf("% d: %d\ n", i, num) 
} 

// 0: 1 

// 1: 2 

// 2: 3

注:我应用了 fmt.Printf(),它容许咱们应用示意十进制整数的 %d 和示意增加行结束符的 \n 来向终端打印任何值。

当不须要应用 index 时,应用这种语法很常见:

for _, num := range numbers {//...}

应用示意 “ 疏忽这个 “ 的非凡 _ 字符,以防止 Go 编译器呈现 “ 你没有应用 i 变量!” 的谬误。

16. 条件式

条件语句的语法和其余语言相似:

if age < 12 {// child} else if age < 18 {// teen} else {// adult}

和其余语言一样,在 if 或者 else 代码块中定义变量,变量的可见范畴等同于代码块的范畴。

如果要应用多个不同的 if 语句来查看一个条件,最好应用 switch

switch age 
{case 0: fmt.Println("Zero years old") 
case 1: fmt.Println("One year old") 
case 2: fmt.Println("Two years old") 
case 3: fmt.Println("Three years old") 
case 4: fmt.Println("Four years old") 
default: fmt.Println(i + "years old") 
}

与 C、JavaScript 和其余语言相比,您不须要在每种状况后都有一个分隔符。

17. 操作符

到目前为止,咱们在代码示例中应用了一些运算符,如 =、:= 和 <。

咱们应用赋值运算符 = 和 := 来申明和初始化变量:

var a = 1 

b := 1

咱们有比拟运算符 == 和 !=,它们承受 2 个参数并返回布尔值。

var num = 1 

num == 1 // true 
num != 1 // false

当然还有上面的内容:

var num = 1 

num > 1 // false 
num >= 1 // true 
num < 1 // false 
num <= 1 // true

咱们有二进制(须要两个参数)算术运算符,如 + - * / %

1 + 1 // 2 
1 - 1 // 0 
1 * 2 // 2 
2 / 2 // 1 
2 % 2 // 0

+ 运算符能够连贯字符串:

"a" + "b" //"ab"

咱们有一元运算符 ++-- 来递增或递加数字:

var num = 1 
num++ // num == 2 
num-- // num == 1

请留神,与 C 或 JavaScript 不同的是,咱们不能像 ++num 那样将它们前置到数字上。

此外,该操作不会返回任何值。

咱们有布尔运算符帮忙咱们依据虚实值做出决定:&&||!

true && true // true 
true && false // false 
true || false // true 
false || false // false 
!true // false 
!false // true

18. 构造

构造体是一种蕴含一个或多个变量的类型。它就像是变量的汇合。咱们称之为字段。它们能够有不同的类型。

上面是定义构造体的代码:

type Person struct { 
    Name string 
    Age int 
}

请留神,我应用了大写字母作为字段名称,否则这些字段将成为软件包的公有字段,当您将构造体传递给另一个软件包提供的函数(如咱们用于解决 JSON 或数据库的函数)时,就无法访问这些字段。

定义构造体后,咱们就能够用该类型初始化变量:

flavio := Person{"Flavio", 39}

能够应用上面的形式获取构造体的字段数据:

flavio.Age // 39 

flavio.Name //"Flavio"

构造体十分有用,因为它能够将不相干的数据分组,并将其传递给函数或从函数中传递进去,还能够存储在片段中,等等。

一旦定义,构造体就是一种相似 int 或字符串的类型,这意味着你也能够在其余构造体外部应用它:

type FullName struct { 

FirstName string 
LastName string 

} 

type Person struct { 

Name FullName 
Age int 

}

19.Functions

函数是一个代码块,它被赋予一个名称,并蕴含一些指令。

在 “ 你好,世界!” 示例中,咱们创立了一个 main 函数,它是程序的入口。

package main import "fmt" func main() { fmt.Println("Hello, World!") }

通常,咱们用自定义名称定义函数:

func doSomething() { 

而后通过上面的形式调用函数:

doSomething()

函数能够承受参数,咱们必须这样设置参数的类型:

func doSomething(a int, b int) { } 

doSomething(1, 2)

a 和 b 是函数外部参数的名称。

函数能够返回一个值,就像上面这样:

func sumTwoNumbers(a int, b int) int {return a + b} 

result := sumTwoNumbers(1, 2)

请留神,这里指定了返回值类型

GO 语言的 return 能够返回超过一个值:

func performOperations(a int, b int) (int, int) {return a + b, a - b} 

sum, diff := performOperations(1, 2)

这很乏味,因为许多语言只容许一个返回值。函数外部定义的任何变量都是函数的局部变量。

函数也能够承受数量不限的参数,在这种状况下,咱们称之为变量函数:

func sumNumbers(numbers ... int) int { 
    sum := 0 
    for _, number := range numbers 
    {sum + = number} 
    return sum 
} 

total := sumNumbers(1, 2, 3, 4)

20. 指针

GO 语言反对应用指针,假如应用上面的变量定义:

age := 20

有了变量指针后,就能够应用 * 运算符获取其指向的值:

age := 20 
ageptr = &age 
agevalue = *ageptr

这在调用函数并将变量作为参数传递时十分有用。

Go 默认将变量值复制到函数外部,因而不会扭转 age 的值:

func increment(a int) {a = a + 1} 

func main() { 
    age := 20 
    increment(age) // age is still 20 
    
}

为此,您能够应用指针:

func increment(a *int) {*a = *a + 1} 

func main() { 

age := 20 
             
 increment(& age) // age is now 21 
 
 }

21. 函数

一个函数能够调配给一个构造体,在这种状况下,咱们称之为办法。

type Person struct {Name string Age int} 

func (p Person) Speak() {fmt.Println("Hello from" + p.Name) 
    
} 


func main() { 

    flavio := Person{ 
        Age: 39, 
        Name: "Flavio"
    } 
    
    flavio.Speak()}

办法参数能够指定指针类型或者值类型,这将是一个指针接收器,用于接管指向构造实例的指针:

func (p *Person) Speak() { fmt.Println("Hello from" + p.Name) }

22. 接口

接口是一种定义了一个或多个办法签名的类型。办法没有实现,只有签名:名称、参数类型和返回值类型。相似于这样:

type Speaker interface {Speak() }

当初,你能够让函数承受任何类型,并实现接口定义的所有办法:

func SaySomething(s Speaker) {s.Speak() 
}

咱们能够将实现这些办法的任何构造传递给它:

type Speaker interface {Speak() 
    
} 

type Person struct {Name string Age int} 

func (p Person) Speak() {fmt.Println("Hello from" + p.Name) 
} 

func SaySomething(s Speaker) {s.Speak() 
}

func main() {flavio := Person{ Age: 39, Name: "Flavio"} 
    SaySomething(flavio) 
}

23. 下一步口头

本手册介绍 Go 编程语言。除了这些基础知识,当初还有很多货色须要学习。

垃圾回收、错误处理、并发和网络、文件系统 API 等等。学习无止境。

我的倡议是,抉择一个你想构建的程序,而后开始学习你须要的货色。这会很乏味,也很有播种。

相干

【Linux】《The Command Line Handbook》读书笔记(上半局部)
【Linux】《The Command Line Handbook》读书笔记(下半局部)

正文完
 0