获得徽章 0
#青训营 x 字节后端训练营# day13
Go pool
1.defer:defer语句会在包含他的函数或者方法的最后一条普通语句执行完毕后执行,然后再执行返回操作。
2.close()函数:一个用于关闭通道的内置函数,通道关闭后不再接收新的元素,但是可以供其他的routine取元素。注意区分和io.Closer接口中的Close方法
3.在这一篇中,用一个结构体来表示一个资源池,结构体中的res字段表示保存的资源,字段是一个有缓冲的通道,这个通道的类型是io.Closer接口,这个接口的方法集中只有一个Close()方法。在本地通过自定义dbConnection结构体类型并为类型添加Close()方法之后,通过这个实体类型来实现了这个接口。
Go pool
1.defer:defer语句会在包含他的函数或者方法的最后一条普通语句执行完毕后执行,然后再执行返回操作。
2.close()函数:一个用于关闭通道的内置函数,通道关闭后不再接收新的元素,但是可以供其他的routine取元素。注意区分和io.Closer接口中的Close方法
3.在这一篇中,用一个结构体来表示一个资源池,结构体中的res字段表示保存的资源,字段是一个有缓冲的通道,这个通道的类型是io.Closer接口,这个接口的方法集中只有一个Close()方法。在本地通过自定义dbConnection结构体类型并为类型添加Close()方法之后,通过这个实体类型来实现了这个接口。
展开
评论
点赞
#青训营 x 字节后端训练营#
day12
byte和rune
1.byte是uint8的别称,rune是int32的别称。
2.byte类型和rune类型使用编码方式不同,其中byte是ASCII编码字符,rune是utf-8字符. 比如可以定义
Var a char = 'a' var b rune = '我'
3.一个byte表示两个十六进制数,本质上用byte[]表示的十进制数是由其表示的十六进制数转换而来的。例如:
十进制1500,对应的十六进制是5dc,存储于一个byte数组arr中,那么将arr此时有两个元素,将这两个元素以十六进制形式输出,结果是:arr[0] = 5; arr[1] = dc;
day12
byte和rune
1.byte是uint8的别称,rune是int32的别称。
2.byte类型和rune类型使用编码方式不同,其中byte是ASCII编码字符,rune是utf-8字符. 比如可以定义
Var a char = 'a' var b rune = '我'
3.一个byte表示两个十六进制数,本质上用byte[]表示的十进制数是由其表示的十六进制数转换而来的。例如:
十进制1500,对应的十六进制是5dc,存储于一个byte数组arr中,那么将arr此时有两个元素,将这两个元素以十六进制形式输出,结果是:arr[0] = 5; arr[1] = dc;
展开
评论
1
#青训营 x 字节后端训练营# day10
new和make的区别
new是初始化指针, 不分配内存;
make分配内存空间, 使用make函数创建map时,可以选择是否指定容量。如果不指定容量,则会创建一个空的map. 如果在使用map时不断地向其中添加元素,map的容量会自动扩容。因此,如果不确定map需要多大的容量,可以不指定容量,让map自动扩容。但是,如果已经确定了map需要存储多少元素,最好还是指定容量,这样可以减少map扩容的次数,提高程序性能。
new和make的区别
new是初始化指针, 不分配内存;
make分配内存空间, 使用make函数创建map时,可以选择是否指定容量。如果不指定容量,则会创建一个空的map. 如果在使用map时不断地向其中添加元素,map的容量会自动扩容。因此,如果不确定map需要多大的容量,可以不指定容量,让map自动扩容。但是,如果已经确定了map需要存储多少元素,最好还是指定容量,这样可以减少map扩容的次数,提高程序性能。
展开
评论
点赞
#青训营 x 字节后端训练营# day 10
Go context
1.context的用法:用context.WithCancel(context.Background())创建一个context对象如ctx和一个cancel()函数,基于这个context对象可以衍生出许多goroutine。调用cannel函数时,所有基于这个ctx衍生的goroutine都会收到一个信号,并退出运行。这是因为在每个 goroutine 中都有一个 select 语句监听着 ctx.Done() 这个 channel。当 ctx 被取消时,这个 channel 就会被关闭,select 语句就会执行 case <-ctx.Done() 这个分支,从而退出 goroutine 的运行。
2.除了WithCancel方法之外还有WithTimeout方法,会多传递一个事件参数,返回值类型一样,时间到了之后会自动执行cancel()函数。
3.不要把Context放在结构体中,要以参数的方式传递
4.以Context作为参数的函数方法,应该把Context作为第一个参数,放在第一位。
5.给一个函数方法传递Context的时候,不要传递nil,如果不知道传递什么,就使用context.TODO
6.Context的Value相关方法应该传递必须的数据,不要什么数据都使用这个传递
7.Context是线程安全的,可以放心的在多个goroutine中传递
Go context
1.context的用法:用context.WithCancel(context.Background())创建一个context对象如ctx和一个cancel()函数,基于这个context对象可以衍生出许多goroutine。调用cannel函数时,所有基于这个ctx衍生的goroutine都会收到一个信号,并退出运行。这是因为在每个 goroutine 中都有一个 select 语句监听着 ctx.Done() 这个 channel。当 ctx 被取消时,这个 channel 就会被关闭,select 语句就会执行 case <-ctx.Done() 这个分支,从而退出 goroutine 的运行。
2.除了WithCancel方法之外还有WithTimeout方法,会多传递一个事件参数,返回值类型一样,时间到了之后会自动执行cancel()函数。
3.不要把Context放在结构体中,要以参数的方式传递
4.以Context作为参数的函数方法,应该把Context作为第一个参数,放在第一位。
5.给一个函数方法传递Context的时候,不要传递nil,如果不知道传递什么,就使用context.TODO
6.Context的Value相关方法应该传递必须的数据,不要什么数据都使用这个传递
7.Context是线程安全的,可以放心的在多个goroutine中传递
展开
评论
点赞
#青训营 x 字节后端训练营# day 9
Go开发工具
1.go build [packages]:
启动编译,若忽略参数则编译当前目录。packages是一个相对于GOROOT和GOPATH两个环境变量的相对路径。
2.跨平台编译:
通过GOOS指定目标操作系统,GOARCH指定目标处理器架构。改变这两个环境变量即可。
3.go clean [packages]:
清除生成的包,避免提交Git时出错。
4.go run:
编译运行合为一布。需要一个go文件做参数,这个文件必须包含main包和main函数,这样才可以运行。可以在命令后面给程序传递参数,参数被存在数组中,从下标一开始存储。
5.go install:
编译后将生成的可执行文件或者库安装到对应的目录下。如果是可执行文件,安装在$GOPATH/bin目录下;如果是可引用的库,安装在$GOPATH/pkg下
Go开发工具
1.go build [packages]:
启动编译,若忽略参数则编译当前目录。packages是一个相对于GOROOT和GOPATH两个环境变量的相对路径。
2.跨平台编译:
通过GOOS指定目标操作系统,GOARCH指定目标处理器架构。改变这两个环境变量即可。
3.go clean [packages]:
清除生成的包,避免提交Git时出错。
4.go run:
编译运行合为一布。需要一个go文件做参数,这个文件必须包含main包和main函数,这样才可以运行。可以在命令后面给程序传递参数,参数被存在数组中,从下标一开始存储。
5.go install:
编译后将生成的可执行文件或者库安装到对应的目录下。如果是可执行文件,安装在$GOPATH/bin目录下;如果是可引用的库,安装在$GOPATH/pkg下
展开
评论
点赞
#青训营 x 字节后端训练营# day 7
init函数:
在 Go 语言中,init 函数是一种特殊的函数,它会在 main 函数执行之前自动执行,用于包级别的一些初始化操作。每个包可以包含任意多个 init 函数,这些函数都会在程序执行开始的时候被调用。
init 函数有以下特点:
- init 函数先于 main 函数自动执行,不能被其他函数调用(所以无需大写)。
- init 函数没有输入参数、返回值。
- 每个包可以有多个 init 函数。
- 包的每个源文件也可以有多个 init 函数。
- 同一个包的 init 执行顺序,Go 语言没有明确定义,编程时要注意程序不要依赖这个执行顺序。
- 不同包的 init 函数按照包导入的依赖关系决定执行顺序。
init函数:
在 Go 语言中,init 函数是一种特殊的函数,它会在 main 函数执行之前自动执行,用于包级别的一些初始化操作。每个包可以包含任意多个 init 函数,这些函数都会在程序执行开始的时候被调用。
init 函数有以下特点:
- init 函数先于 main 函数自动执行,不能被其他函数调用(所以无需大写)。
- init 函数没有输入参数、返回值。
- 每个包可以有多个 init 函数。
- 包的每个源文件也可以有多个 init 函数。
- 同一个包的 init 执行顺序,Go 语言没有明确定义,编程时要注意程序不要依赖这个执行顺序。
- 不同包的 init 函数按照包导入的依赖关系决定执行顺序。
展开
评论
点赞
#青训营 x 字节后端训练营# day7
在Go语言中,goroutine是一种轻量级的线程(也称为协程),用于并发执行代码。它是Go语言并发模型的核心组件,允许我们以一种简单而高效的方式编写并发代码。
goroutine的特点如下:
轻量级:与传统的线程相比,goroutine的创建和销毁开销非常小。可以在一个程序中创建成千上万个goroutine而不会导致资源的过度消耗。
并发性:通过使用goroutine,我们可以在程序中同时执行多个任务,这些任务可以是独立的,不需要进行显式的线程同步。
通信机制:goroutine之间可以通过通道(channel)进行通信。通道是一种特殊的数据结构,可以用于在goroutine之间传递数据,并提供了同步的机制。
内部调度:Go语言的运行时系统负责在多个goroutine之间进行内部调度,以便高效地利用计算资源。这使得我们无需担心手动管理线程的细节,而可以专注于编写并发代码的逻辑。
在Go语言中,goroutine是一种轻量级的线程(也称为协程),用于并发执行代码。它是Go语言并发模型的核心组件,允许我们以一种简单而高效的方式编写并发代码。
goroutine的特点如下:
轻量级:与传统的线程相比,goroutine的创建和销毁开销非常小。可以在一个程序中创建成千上万个goroutine而不会导致资源的过度消耗。
并发性:通过使用goroutine,我们可以在程序中同时执行多个任务,这些任务可以是独立的,不需要进行显式的线程同步。
通信机制:goroutine之间可以通过通道(channel)进行通信。通道是一种特殊的数据结构,可以用于在goroutine之间传递数据,并提供了同步的机制。
内部调度:Go语言的运行时系统负责在多个goroutine之间进行内部调度,以便高效地利用计算资源。这使得我们无需担心手动管理线程的细节,而可以专注于编写并发代码的逻辑。
展开
评论
点赞
#青训营 x 字节后端训练营# day4
Go 切片
1.切片基于底层数组,更改切片的值也会更改底层数组。切片创建时不初始化默认也为零值
2.切片的数据结构包含:指向底层数组的指针、切片长度、切片容量(对应切片的底层数组)。切片容量>=切片 长度,只能访问切片长度的值,剩下的值要切片扩充后才能访问。
3.切片创建的三种方式:
1.make方式:slice := make([]int,5,10),5代表长度,10代表容量,不指定容量则默认等于长度
2.字面量方式:slice :=[]int{4:1},和数组唯一的不同是不用指定[]的值
3.基于已有的数组或切片创建:slice1:= slice[i:j],长度为j-i,容量为k-i
Go 切片
1.切片基于底层数组,更改切片的值也会更改底层数组。切片创建时不初始化默认也为零值
2.切片的数据结构包含:指向底层数组的指针、切片长度、切片容量(对应切片的底层数组)。切片容量>=切片 长度,只能访问切片长度的值,剩下的值要切片扩充后才能访问。
3.切片创建的三种方式:
1.make方式:slice := make([]int,5,10),5代表长度,10代表容量,不指定容量则默认等于长度
2.字面量方式:slice :=[]int{4:1},和数组唯一的不同是不用指定[]的值
3.基于已有的数组或切片创建:slice1:= slice[i:j],长度为j-i,容量为k-i
展开
评论
点赞
#青训营 x 字节后端训练营# day2
1.Map存储一系列无序的键值对,基于哈希表实现,每次迭代Map时打印的Key和Value都无序。原理是将键传给哈希函数,索引到相应的桶(就是hash解决冲突中用到的链条法,hash结果相同的链接到同一个链表上,称为桶),进而找到相应的键值。存储的数据越多,索引分布越均匀,访问键值对的速度越快。
2.Map的两种创建方式:
1.make函数:dict := make(map[string]int),键就相当于索引,所以用[],使用:dict["norwich"]=18
2.map字面量:dict := map[string]int{"norwich":18},{}可以为空,多个键值对用,分割。总之要有{}。
3.创建nil的map:nil代表为初始化,既不能用字面量也不能用make分配内存,只能声明一个变量:
var dict map[string]int
之后要使用的话还是要用make开辟内存:dict := make(map[string]int)
4.Map的键需要能够做==运算,像切片、函数以及含有切片的结构类型不能用于Map的键,因为它们具有引用
语义,不能比较。Map的值可以是任何类型
1.Map存储一系列无序的键值对,基于哈希表实现,每次迭代Map时打印的Key和Value都无序。原理是将键传给哈希函数,索引到相应的桶(就是hash解决冲突中用到的链条法,hash结果相同的链接到同一个链表上,称为桶),进而找到相应的键值。存储的数据越多,索引分布越均匀,访问键值对的速度越快。
2.Map的两种创建方式:
1.make函数:dict := make(map[string]int),键就相当于索引,所以用[],使用:dict["norwich"]=18
2.map字面量:dict := map[string]int{"norwich":18},{}可以为空,多个键值对用,分割。总之要有{}。
3.创建nil的map:nil代表为初始化,既不能用字面量也不能用make分配内存,只能声明一个变量:
var dict map[string]int
之后要使用的话还是要用make开辟内存:dict := make(map[string]int)
4.Map的键需要能够做==运算,像切片、函数以及含有切片的结构类型不能用于Map的键,因为它们具有引用
语义,不能比较。Map的值可以是任何类型
展开
评论
点赞
#青训营 x 字节后端训练营# 关于Go的并发资源竞争:
1.对于同一个资源的读写必须是原子化的,同一时间只能有一个goroutine对共享资源进行读写操作
2.go build -race命令可以生成自带检测资源竞争功能的可执行函数
3.sync/atomic中含有一些原子函数可以保证并发下资源同步访问修改的问题,但是存在一些问题。
4.sync/Mutex提供互斥锁,被互斥锁控制的代码范围称为临界区,临界区的代码同一时间只能由一个goroutine访问。声明一个变量var mutex sync.Mutex,然后用mutex.Lock(),mutex.Unlock()构建临界区
1.对于同一个资源的读写必须是原子化的,同一时间只能有一个goroutine对共享资源进行读写操作
2.go build -race命令可以生成自带检测资源竞争功能的可执行函数
3.sync/atomic中含有一些原子函数可以保证并发下资源同步访问修改的问题,但是存在一些问题。
4.sync/Mutex提供互斥锁,被互斥锁控制的代码范围称为临界区,临界区的代码同一时间只能由一个goroutine访问。声明一个变量var mutex sync.Mutex,然后用mutex.Lock(),mutex.Unlock()构建临界区
展开
评论
点赞