Go语言强化训练篇
2022-11-09 打卡
知识点总结
- golang中的字符串细节
src := "abcde"
src[0] = "c"
- 错误原因:golang中字符串不能改变
- 注:golang中字符串下标可以参与运算,但是不能用于修改赋值
- Json处理机制
- json在序列化遇到管道/函数等无法被序列化的情况时,会发生error错误。
- channel、function、complex、循环引用的数据类型不能被json.Marshal序列化
- json在序列化遇到管道/函数等无法被序列化的情况时,会发生error错误。
- go语言常量细节
- go语言常量要是编译时就能确定的数据,不能赋值不确定的值,存储在常量中的数据类型只可以是 不能存在任何可变元素 的值。
- errors.New(“xxx”) 要等到运行时才能确定,所以它不满足
- 在 Go 语言中,你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型
- go中全局变量和局部变量的处理
-
全局变量: 在函数外部定义的变量,称为全局变量;
-
作用域:同一个包内任何地方;
-
全局变量,首字母大写,可以跨包访问;
-
小写,则只可以在本包内访问;
-
全局变量,不能使用:=(短变量)进行赋值创建,会出现编译异常;
-
-
局部变量: 定义在{}里面的变量为局部变量;
- 作用域:只能在{}里面有效;执行到定义的那句话,开始分配内存空间,离开作用域自动进行释放;
- 局部变量只能在函数内部进行声明;
-
全局变量只能通过var声明;
- go关键字及其作用:
var
和const
:变量和常量的声明var varName type
或者 varName : = valuepackage
andimport
: 导入func
: 用于定义函数和方法return
:用于从函数返回defer
someCode :在函数退出之前执行go
: 用于并行select
用于选择不同类型的通讯interface
用于定义接口struct
用于定义抽象数据类型break、case、continue、for、fallthrough、else、if、switch、goto、default
流程控制chan
用于channel通讯type
用于声明自定义类型map
用于声明map类型数据range
用于读取slice、map、channel
数据
- go语言中的垃圾回收机制
- Go自带垃圾回收器,每次更新垃圾回收器必然是核心组件里修改最多的部分。
- 从并发清理,到降低 STW 时间,直到 Go 的 1.5 版本实现并发标记,逐步引入三色标记和写屏障等等,都是为了能让垃圾回收在不影响用户逻辑的情况下更好地工作。尽管有了努力,当前版本的垃圾回收算法也只能说堪用,离好用尚有不少距离。
2022-11-10 打卡
知识点总结
-
go语言内置函数 delete
-
内置函数 delete 只能删除 map,参见源码:
-
func delete(m map[Type]Type1, key Type)
-
-
- go数组是不可变类型,切片的删除没有指定的内置函数,也不能直接删除,都是通过切片的拼接进行的,
s=append(s[i:],s[i+1:])
(append可以对切片进行初始化操作)
- go语言panic知识点
-
由panic引发异常以后,程序停止执行,然后调用延迟函数(defer),就像程序正常退出一样。另外recover也是要写在延迟函数中的,如果发生异常延迟函数就不执行了,那就永远无法recover了。
-
异常发生后,panic之前的defer函数会被执行,但是panic之后的defer函数并不会被执行
-
go语言channel
- nil channel代表channel未初始化,向未初始化的channel读或写数据都会造成永久阻塞。
- 从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回一个零值
- 关闭(close)未初始化的channel会引起panic。
- nil channel代表channel未初始化,向未初始化的channel读或写数据都会造成永久阻塞。
-
go语言的匿名函数定义
-
// 赋值给变量执行 a := func() { println("assign to var and execute") } a() // 直接执行 func() { println("direct execute") }()
- 匿名函数可以直接赋值给一个变量或者直接自执行
-
-
go语言中interface{}
- interface{}对应的type是
runtime.eface
是可以接收任意类型的,本身也是具有确定类型的
- interface{}对应的type是
2022-11-11 打卡
知识点总结
-
go语言中有哪些类型可以自定义方法->(除了指针都可以)
-
定义方法必须指定方法的接收者。方法的接收者可以是内置类型、自定义结构体,不能是指针(比如:&p)
-
几乎所有类型包括内置类型,均可以自定义方法。除了指针。
func (a *Integer) Multi(b Integer){}
-
-
go语言中传递参数只有值传递,没有引用传递(详情查看GO语言圣经)
-
package main import ( "sync" "sync/atomic" ) func main() { var wg sync.WaitGroup ans := int64(0) for i := 0; i < 3; i++ { wg.Add(1) go newGoRoutine(wg, &ans) } wg.Wait() } func newGoRoutine(wg sync.WaitGroup, i *int64) { defer wg.Done() atomic.AddInt64(i, 1) return }
-
sync.Waitgroup 里面有 noCopy 结构,不应该使用值拷贝,只能使用指针传递。
-
函数newGoRoutine 的第一个传参类型为sync.WaitGroup,传入的值并不是原先main函数中的值,而是该参数的值拷贝。最终只是将函数内部的wg进行了关闭,而main函数中的wg会堵塞造成死锁。
- go vendor 机制
- 无法精确的引用外部包进行版本控制,不能指定引用某个特定版本的外部包;只是在开发时,将其拷贝过来,但是一旦外部包升级,vendor下的代码不会跟着升级
- 而且vendor下面并没有元文件记录引用包的版本信息,这个引用外部包升级产生很大的问题,无法评估升级带来的风险;
- Go语言中的main函数
-
关于main函数(可执行程序的执行起点)
-
Main函数和init函数都没有参数和返回值的定义
-
main函数所在的包必须为main包
-
main函数中可以使用flag包来获取和解析命令行参数
-
go语言channel
-
无缓冲的channel是同步的,而有缓冲的channel是非同步的
比如
c1:=make(chan int) 无缓冲 c2:=make(chan int,1) 有缓冲 c1<-1
-
无缓冲的 不仅仅是 向 c1 通道放 1 而是 一直要有别的携程 <-c1 接手了 这个参数,那么c1<-1才会继续下去,要不然就一直阻塞着
-
而 c2<-1 则不会阻塞,因为缓冲大小是1 只有当 放第二个值的时候 第一个还没被人拿走,这时候才会阻塞。
打个比喻
无缓冲的 就是一个送信人去你家门口送信 ,你不在家 他不走,你一定要接下信,他才会走。
无缓冲保证信能到你手上
有缓冲的 就是一个送信人去你家仍到你家的信箱 转身就走 ,除非你的信箱满了 他必须等信箱空下来。
有缓冲的 保证 信能进你家的邮箱
-
2022-11-12 打卡
知识点总结
-
go语言数据类型分为四类:
-
基础类型,基础类型又分为三种
- 数字。包括整型,浮点型,无符号整型
- 字符串
- 布尔型
-
复合类型,通过组合简单的类型,来表达更加复杂的数据结构
- 数组
- 结构体
-
引用类型,凡是能表示为nil的都为引用类型(因为其内部构成都有一个指针)
- 指针(pointer *)
- 切片(slice)
- 字典(map,也叫映射)
- 管道(channel)
- 函数
-
接口类型,对其它类型行为的抽象和概括
-
-
go语言中常量的知识点
- Go语言的常量有个不同寻常之处。虽然一个常量可以有任意有一个确定的基础类型,例如int或float64,或者是类似
time.Duration
这样命名的基础类型,但是许多常量并没有一个明确的基础类型。编译器为这些没有明确的基础类型的数字常量提供比基础类型更高精度的算术运算;你可以认为至少有256bit
的运算精度。这里有六种未明确类型的常量类型,分别是无类型的布尔型、无类型的整数、无类型的字符、无类型的浮点数、无类型的复数、无类型的字符串。
- Go语言的常量有个不同寻常之处。虽然一个常量可以有任意有一个确定的基础类型,例如int或float64,或者是类似
-
go语言切片
- map和slice在使用前都需要进行初始化操作,
append
也可以进行切片初始化操作
- map和slice在使用前都需要进行初始化操作,
-
go语言Json序列化操作
- json无法序列化 管道、函数、complex。并且在进行结构体序列化时,只能序列化首字母大写的变量。
2022-11-13 打卡
知识点总结
-
select和switch语句
- 单个case可以有多个结果:case 4, 5, 6:…
- switch 中的表达式是可选的,可以省略。如果省略表达式,则相当于 switch true,这种情况下会将每一个 case 的表达式的求值结果与 true 做比较,如果相等,则执行相应的代码。
- go语言中无需使用break退出case。在执行完每个case之后会自动退出,除非使用fallthrough
- select机制用来处理异步IO问题。select有比较多的限制,其中最大的一条限制就是每个case语句里必须是一个IO操作。确切的说,应该是一个面向channel的IO操作。
-
同步锁,RW读写锁
- RWMutex.RLock()时,可以随便读。多个goroutin同时读。不能写。
- RWMutex.Lock()时(写的时候),啥都不能干。不能读,也不能写。
- 当一个goroutine获得了Mutex后,其他goroutine就只能乖乖的等待,除非该goroutine释放这个Mutex
- 无论是RWMutex还是Mutex,与Lock()对应的都是Unlock()
-
CGO
- CGO是C语言和Go语言之间的桥梁,原则上无法直接支持C++的类。CGO不支持C++语法的根本原因是C++至今为止还没有一个二进制接口规范(ABI)。CGO只支持C语言中值类型的数据类型,所以我们是无法直接使用C++的引用参数等特性的。
-
Go语言中取反操作
- Go语言取反方式和C语言不同,Go语言不支持~符号
- 如果想要取反,需要使用
^x
来进行取反
-
Go语言中
int
和uint
取值范围- int 和 uint 的取值范围与体系架构有关,在 32 位机中等价于 int32 和 uint32,在 64 位机中等价于 int64 和 uint64。
-
自定义方法
-
几乎所有类型包括内置类型,均可以自定义方法。除了指针。
func (a *Integer) Multi(b Integer){}
-
-
关于函数返回值的错误设计
- 如果失败原因只有一个,则返回bool
- 如果失败原因超过一个,则返回error
- 如果没有失败原因,则不返回bool或error
- 如果重试几次可以避免失败,则不要立即返回bool或error (Go语言圣经中有提到例子)
-
golong垃圾回收机制
- go语言的自动内存管理机制使得只要还有一个指针引用一个变量,那这个变量就会在内存中得以保留,因此在Go语言函数内部返回指向本地变量的指针是安全的。
2022-11-14 打卡
知识点总结
- cap函数的适用类型
- cap的作用—— arry:返回数组的元素个数 slice:返回slice的最大容量 channel:返回channel的buffer容量
- cap函数不支持map,map中使用len表示大小
- init函数使用规则
- init函数可以在任何包中有0个或1个或多个;
- 首先初始化导入包的变量和常量,然后执行导入包的init函数,最后初始化本包的变量和常量,然后初始化本包init函数,最最后是main函数;
- main函数只能在main包中有且只有一个,main包中也可以有0或1或多个init函数;
- init函数和main函数都不能被显示调用,都是由系统隐式调用执行;
- 运行错误机制处理
- 当程序运行时,如果遇到引用空指针、下标越界或显式调用panic函数等情况,则先调用defer,然后触发panic函数的执行,然后调用延迟函数。调用者继续传递panic,因此该过程一直在调用栈中重复发生:函数停止执行,调用延迟执行函数。协程会遍历所有调用栈上需要执行的defer,如果执行完这些defer没有遇到recover,会直接调用exit退出程序