Go Study

​ 相关代码见:https://github.com/WD-2711/go-study

Go-section-2

运行go程序的方式:

  1. go run xx.go
  2. go install xx.go,之后可以用$GOPATH/bin/xx 运行该程序
1
2
3
4
5
package main
import "fmt"
func main() {
fmt.Println("Hello World")
}

Go-section-3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var age int
fmt.Println("my age is", age)
age = 29
fmt.Println("my age is", age)
age = 54
fmt.Println("my age is", age)
var age int = 29
fmt.Println("my age is", age)
var age = 30
fmt.Println("my age is", age)
var width, height int = 100, 50
fmt.Println("width is", width, "height is", height)
var (
name = "naveen"
age = 29
height int
)
fmt.Println("my name is ", name, ", age is ", age, "and height is ", height)
a, b := 20, 30
a, b := 40, 50
fmt.Println(a, b)

输出如下:

1
2
3
4
5
6
7
8
9
my age is 0
my age is 29
my age is 54
my age is 29
my age is 30
width is 100 height is 50
my name is naveen , age is 29 and height is 0
40 50
6 <nil>

Go-section-4

基本数据类型:

1
2
3
4
5
6
7
int8,int16,int32,int64,int
uint8,uint16,uint32,uint64,uint
float32,float64
complex64,complex128
byte
rune
string

具体见/go-class/dataType.go

Go-section-5

具体见/go-class/constVar.go

Go-section-6

具体见/go-class/func.go

Go-section-7 包

  1. 创建geometry文件夹,编写完geometry.go,运行cp -r /root/code/go-code/go-class/sec-7/geometry /usr/local/go/src,接着cd /usr/local/go/src运行 go install geometry,这个时候就会在/usr/local/go/bin文件夹下生成一个geometry的可运行程序
  2. cd /usr/local/go/bin && ./geometry 即可

创建自定义的包

  1. 在geometry文件夹中创建rectangle文件夹并在里面编写rectprops.go文件,按上述操作进行运行

导出名

  1. rectprops.go中的函数首字母都是大写的,这代表可以被导出,其他包可以访问到这些函数

Init

  1. 所有包中都可以包含Init函数,此函数没有任何返回值与参数,其用于初始化任务,也可以在程序开始执行之前验证程序的正确性
  2. 包的初始化顺序如下:(1)初始化包级别的变量。(2)调用Init函数(一个包中可以有多个Init函数)

注:一个包可以被导入多次,但是它只会被初始化一次。

空白标识符

  1. 导入了包,但是不在代码中使用它是违法的。
  2. 可以用空白标识符来避免这种问题:
1
import (_ "geometry/rectangle")

具体见/go-class/sec-7

Go-section-8 分支语句

一个很坑的点就是:(原因是go看到}后面没有字符就自动插入;)

要这么写

1
2
3
4
5
if condition {
xxx
} else {
xxx
}

不能这么写

1
2
3
4
5
6
if condition {
xxx
}
else {
xxx
}

具体见/go-class/ifElse.go

Go-section-9 循环

具体见/go-class/cycle.go

Go-section-10 switch

  1. case 不允许出现重复项
  2. fallthrough意思是执行完一个case之后,不会跳出来,反而进行下一个case的判断

具体见/go-class/switch.go

Go-section-11 array&切片

具体见/go-class/arr-slice.go

Go-section-12 Maps

  1. map是将value与key关联的数据类型

具体见/go-class/maps.go

Go-section-13 字符串

具体见/go-class/str.go

Go-section-14 可变参数函数

  1. 可变参数函数就是参数个数可以改变的函数,其最后一个参数为...T,例如
1
func append(slice []Type, elems ...Type) []Type

具体见/go-class/argChangeFuc.go

Go-section-15 指针

1.指针变量的类型为*T,该指针指向了一个T类型的变量

具体见/go-class/pointer.go

Go-section-16 结构体

具体见/go-class/structure.go与/go-class/sec-16

sec-16主要是讲导出结构体

1
2
3
4
cp -r /root/code/go-code/go-class/sec-16/structs /usr/local/go/src
cd /usr/local/go/src
go install structs
cd /usr/local/go/bin && ./struct

具体见/go-class/structure.go

Go-section-17 方法

  1. 方法其实就是函数,只不过在func与方法名之间加了一个特殊的接收器类型,例如:
1
2
func (t Type) methodName (params list){
}
  1. 为啥需要方法呢?(1)Go不支持类,且不是纯粹的面向对象的编程语言,基于类型的方法是一种实现和类相似行为的途径。(2)相同名字的方法可以定义在不同的类型上,而相同名字的函数是不被允许的。

  2. 什么时候用指针接收器,什么时候用值接收器?当要求方法内部的接收器的所做的改变对调用者可见时,要用指针接收器。

  3. 方法中的值接收器 and 函数中的值参数。(1)当函数中是值参数,它只能接受值参数;当方法中有一个值接收器,那么它可以接受值接收器和指针接收器。(2)当函数中是指针参数,那么它只能接受指针参数;当方法中一个指针接收器,那么它可以接受值接收器和指针接收器。

具体见/go-class/method.go

Go-section-18 接口(重点)

  1. 接口定义一个对象的行为,接口只定义了对象应该做什么,但是要怎么去做还是要对象本身去决定。

  2. Go中,接口就是方法的集合。当一个类型定义了接口中的所有方法,我们就说它实现了该接口。

具体见/go-class/interface.go

Go-section-19 接口2(重点)

具体见/go-class/interface2.go

Go-section-20 并发

  1. 并发与并行的区别(你懂的)

Go-section-21 协程

  1. 啥是协程?协程是与其他函数或方法一起并发运行的函数或方法,可以看作是轻量级的线程。

  2. 协程相对于线程的优势?(1)成本极低。堆栈大小只有几kb。(2)协程复用数量更少的OS线程。如果线程中的某一个协程发生了阻塞,那么系统会创建一个新的OS线程,并把其余的Go协程都移动到这个新的OS线程。(3)协程使用信道来通信。

具体见/go-class/coroutine.go

Go-section-22 信道

具体见/go-class/channel.go

Go-section-23 缓冲信道与工作池(重点)

  1. 啥是缓冲信道?就是有容量的信道。

  2. 缓冲信道的长度指的是当前存的值的数量,缓冲信道的容量就是最多能放多少值。

  3. WaitGroup用于等待一批协程执行结束,直到这些协程全执行完毕后,程序才会继续往下运行。

  4. 工作池就是一组等待任务分配的线程,一旦完成了所分配的任务,这些线程可以继续等待任务的分配。pool.go中写了一个工作池,其功能如下:(1)创建了一个Go协程池,监听一个等待作业分配的输入型缓冲信道。(2)将作业添加到输入型缓冲信道中。(3)作业完成后,将结果写入到一个输出型缓冲信道。(4)从输出型缓冲信道中读取并打印结果。

具体见/go-class/pool.go

Go-section-24 select

  1. select会在多个发送/接收信道操作中进行选择,select会一直阻塞,直到发送/接收操作准备就绪。如果有多个信道准备完毕,那么select会随机选取其中之一执行。

  2. select的应用:想要把输出尽快的返回给用户,输出存储在世界各地的服务器上。

具体见/go-class/select.go

Go-section-25 mutex

  1. mutex就是互斥量,相应的就有临界区的概念,你也懂得哦
1
2
3
mutex.Lock()
x = x + 1
mutex.Unlock()

Lock与Unlock之间的代码只能由一个Go协程执行,所以可以避免竞态条件。

具体见/go-class/mutex.go

Go-section-26 结构体取代类

  1. Go虽然没有类,但是也可以面向对象编程,就是用接口和结构体来实现类的功能。

具体见/go-class/sec-26

Go-section-27 组合取代继承

意思就是多个结构体嵌套,然后用切片可以组合在一起。

具体见/go-class/nest.go

Go-section-28 defer

  1. defer的定义:含有defer的函数,在函数要返回之前,调用另一个函数。

  2. defer的应用:当函数在当前代码流无关的环境下调用时,可以使用defer。

具体见/go-class/defer.go

Go-section-29 多态

  1. 同一个代码可以在多种不同的类型上运行,例如:
1
2
3
func printValue(val interface{}) {
fmt.Println(val)
}

具体见/go-class/defer.go

Go-section-30 错误

  1. error是一个接口,定义如下:
1
2
3
type error interface {
Error() string
}

具体见/go-class/errProcess.go

Go-section-31 自定义错误

  1. 使用New函数创建自定义错误

具体见/go-class/errUserDefine.go

Go-section-32 panic与recover

  1. 上一节说的error是用来处理异常情况的,一般来说error就够用了。但是有些情况,当程序发生异常时无法继续运行,这种情况下我们会使用panic来终止程序,当函数发生panic的时候,在执行完所有的延迟函数后,程序会中止运行。

  2. 当程序出现panic的时候,使用recover可以重新获得对该程序的控制权

  3. panic&recover与try-catch-finally类似。

  4. panic的使用场景:(1)发生了不能恢复的错误,例如web服务器无法绑定所要求的端口,因为如果不能绑定端口,那么啥也做不了。(2)发生了编程上的错误,例如有一个接收指针参数的方法,而其他人使用nil作为参数调用了它,此时可以使用panic,因为用nil参数调用了一个只能接收合法指针的方法。

留言

2023-02-10

© 2024 wd-z711

⬆︎TOP