8000 Add 2021-3-29-gopl1.md · vltavaw/vltavaw.github.io@c4b61b3 · GitHub
[go: up one dir, main page]

10000 Skip to content

Commit c4b61b3

Browse files
authored
Add 2021-3-29-gopl1.md
1 parent e97db53 commit c4b61b3

File tree

2 files changed

+168
-18
lines changed

2 files changed

+168
-18
lines changed

_posts/2016-08-29-example-post-three.md

Lines changed: 0 additions & 18 deletions
This file was deleted.

_posts/2021-3-29-gopl1.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
---
2+
title: GoPL读书笔记1
3+
categories:
4+
- Go
5+
---
6+
7+
8+
### Ch.1
9+
第一章是例子oriented的,内容相对散乱。
10+
1. Go是编译型语言。使用`go run`运行程序,`go build`生成binary。
11+
2. Go看起来让人想到Rust那个跟麦格教授一样严格的编译器。import的package必须使用,不需要的变量应该使用`_`表示空标识符。Go并没有相对温和~~可以忽视~~的warning,要么是error要么编译通过,可以说force了良好的编程习惯?
12+
3. 同样的严格在formatting上也有所体现。gofmt会把所有代码重写为唯一的标准格式,虽然非常强硬,但是也使得自动化的代码工具成为了可能。
13+
4. Go只有for一种循环,但它可以通过条件的缺省做到多种用法。
14+
15+
```go
16+
//常规循环,不需要加括号
17+
for initialization; condition; post {
18+
// ...
19+
}
20+
21+
// 省略初始化和post,就可以变为while loop
22+
for condition {
23+
// ...
24+
}
25+
// 省略全部条件,则变为死循环。当然可以使用break/return跳出循环
26+
for {
27+
// ...
28+
}
29+
30+
//使用range关键字,成为for each loop
31+
for idx, n := range arr {
32+
// ...
33+
}
34+
```
35+
36+
5. Go最标志性的特性应该就在于concurrent programming了。通过`go`关键字调用函数,可以创建goroutine进行并行操作。goroutine之间通过channel进行thread safe的通信。下面这个例子并行地将两个等长的数组element-wise地相加,通过channel传回结果并且print。
37+
38+
```go
39+
func add(a, b int, result chan int) int {
40+
result <- a + b
41+
}
42+
43+
func main() {
44+
arr1 = ...
45+
arr2 = ...
46+
result := make(chan int)
47+
for i, _ := range arr1 {
48+
go add(arr1[i], arr2[i], result)
49+
fmt.Println(result)
50+
}
51+
}
52+
```
53+
54+
### Ch.2
55+
1. Go有25个关键字和30多个预声明的常量/类型/函数。前者无法作为名称,只能用在语法所指定的地方,但后者可以被重定义(注意作用域)。
56+
2. 变量的命名风格:大写字母而非下划线,缩写词使用同样的大小写。
57+
3. Go程序的基本结构包括:package声明,import声明,包level的变量/函数等声明。
58+
59+
```go
60+
package main
61+
62+
import (
63+
"fmt"
64+
"io"
65+
...
66+
)
67+
68+
const c = ...
69+
70+
func foo() {
71+
// ...
72+
}
73+
74+
func main() {
75+
// ...
76+
}
77+
```
78+
79+
4. 函数的声明包括:函数的名字,参数列表,返回值列表,函数体。其中返回值可以省略。
80+
81+
```go
82+
func fToC(f float64) float64 {
83+
// body
84+
}
85+
```
86+
87+
5. 变量的声明的通用格式是:
88+
89+
```go
90+
var name type = expr
91+
```
92+
可以省略type,让类型由type inference推导;也可以省略初始值,那么变量会被初始化为对应类型的零值(0,false,空字符串,nil指针等等),这被称为零值机制。零值机制保证了所有变量都被良好地初始化了,减少了undefined behavior。我们也可以使用短声明来声明变量:
93+
94+
```go
95+
name := expr
96+
```
97+
这种声明对于局部变量比较常见。需要注意`:=`代表声明而`=`代表赋值,我们也可以进行多重赋值和多重声明:
98+
99+
```go
100+
var b, f, s = true, 2.3, "four" //会被分别推导为bool, float64, string
101+
i, j := 0, 1
102+
i, j = j, i //交换i,j
103+
```
104+
可以看到Go的多重赋值可以很方便地进行交换或者更多的操作。我们还可以在短声明里同时混杂声明和赋值,但是当我们使用`:=`的时候,语句里必须至少有一个声明才行。
105+
106+
```go
107+
f, err := os.Open(f1)
108+
f, err := os.Open(f2) // 编译不通过,因为没有声明新的变量,应该使用=而非:=
109+
```
110+
111+
6. 指针的声明可以通过普通声明或者是`new`函数。
112+
113+
```go
114+
x := 1
115+
p1 := &x
116+
p2 := new(int)
117+
*p2 = 2
118+
```
119+
120+
7. 类型的声明是包级别的,对整个package都可见。如果类型的名字大写,那么其他的包也可以导入这个类型。
121+
122+
```go
123+
type name underlying-type
124+
```
125+
自定义的类型之间可以显式地转换,但不可以直接进行运算,就算它们本来属于一样的底层类型也不可以。
126+
127+
```go
128+
type Celsius float64
129+
type Fahrenheit float64
130+
131+
var f Fahrenheit
132+
var c Celsius
133+
f = c*9/5 +32 // error
134+
f = Fahrenheit(c*9/5 +32) // ok
135+
```
136+
137+
8. Go中的包(package)和其他语言中类似的概念相似。它支持模块化、封装、提供了独立的namespace。我们通过命名的大小写控制可见性:大写字母开头的indentifier对外可见。包的初始化会从包级别变量开始,并且可以自动解析dependency:
138+
139+
```go
140+
var a = b + c // 最后再初始化a
141+
var b = f() // 然后调用f来初始化b
142+
var c = 1 // 首先初始化c
143+
func f() int { return c + 1 }
144+
```
145+
我们还可以通过`init`函数来对包进行初始化。`init`函数可以在同一个文件里声明多次,不可以被调用或者引用,只会在程序启动的时候按照声明的顺序执行。
146+
147+
9. 作用域和生命周期的区别:生命周期是运行时属性,而作用域是编译时属性。像其他语言一样,Go从内到外逐级在词法块(block)里寻找名字的声明,并且引用最近的一个。特别注意的是如果使用`:=`进行多重声明,就不会对外部变量赋值而是创建一个新的变量:
148+
149+
```go
150+
var cwd string // global
151+
152+
func init() {
153+
cwd, err := os.Getwd()
154+
// ...
155+
}
156+
```
157+
在上述init函数中,不会给全局变量cwd赋值,而是在函数内部新建了一个cwd变量,同时还会导致未使用cwd的编译错误。最简单的方法是不要使用`:=`了:
158+
159+
```go
160+
var cwd string // global
161+
162+
func init() {
163+
var err error
164+
cwd, err = os.Getwd()
165+
// ...
166+
}
167+
```
168+
Placeholder

0 commit comments

Comments
 (0)
0