笔记
defer是Go语言中的关键字,用于延迟执行函数调用。当一个函数使用defer关键字调用另一个函数时,被调用的函数不会立即执行,而是在包含它的函数执行完毕后再执行。
切片是Go语言中一种灵活的数据结构,可以存储一系列元素。切片可以通过索引来访问元素,并且可以根据需要对切片进行切取操作。例如,a[:i]表示从切片开头到索引位置i(不包括索引i)的元素;a[i+1:]表示从索引位置i+1开始(包括索引i+1),切取到切片a的末尾的元素。
函数是一种可重复使用的代码块,用于完成特定的任务。在Go语言中,函数和操作对象的类型紧密地绑定在一起。我们可以给任何自定义类型添加一个或多个方法,每个方法必须和类型的定义在同一个包中。但是,无法给内置类型(如int)添加方法。每个方法的名字必须是唯一的,不支持方法的重载。
接口是一种抽象类型,用于定义一组方法的集合。在Go语言中,接口类型是对其他类型行为的抽象和概括。接口可以让对象更加灵活和适应不同的情境。接口类型是满足隐式实现的鸭子类型,即只要一个对象实现了接口定义的所有方法,就认为该对象实现了该接口。
通道是Goroutine之间通信的机制。通道可以用于在不同的Goroutine之间传递数据。通道分为无缓冲区通道和有缓冲区通道。无缓冲区通道是同步通道,发送和接收操作需要同时准备好;有缓冲区通道可以缓存一定数量的元素,发送和接收操作可以异步进行。
协程(Goroutine)是Go语言并发编程的执行体。通过使用go关键字可以创建并发执行的协程。协程可以与其他协程并发执行,实现并发编程的效果。协程可以通过通信来共享内存,而不是通过共享内存来实现通信。
锁(sync.Mutex)是一种并发编程中的同步机制,用于保护共享资源的访问。通过对共享资源加锁,可以确保在同一时刻只有一个协程可以访问该资源,从而避免并发访问导致的数据竞争问题。
WaitGroup是Go语言中的一个同步原语,用于等待一组协程执行完毕。可以通过Add方法设置等待的协程数量,通过Done方法标记协程执行完毕,通过Wait方法等待所有协程完成。
当使用defer关键字调用函数时,会将函数推迟到所在的函数返回之前执行。这种机制经常用于资源释放、错误处理和日志记录等场景。defer语句可以用在普通函数、方法以及匿名函数中。
切片是Go语言中一种灵活且强大的数据类型,它是对数组的一个封装。切片拥有可变长度,并且可以动态地增加或减少元素。切片的底层是一个数组,但是切片的长度不可直接修改;而通过切片表达式,可以方便地截取切片的一部分作为新的切片。切片还支持追加元素、复制切片、遍历切片等操作。
函数是一种可重复使用的代码块,用于完成特定的任务。在Go语言中,函数可以有多个输入参数,也可以有多个返回值。函数可以定义在包级别,也可以定义在结构体类型上,成为方法。函数也可以作为参数传递给其他函数,或者作为返回值。
接口是一种抽象类型,用来定义对象的行为规范。接口由一组方法签名组成,没有具体的实现。一个类型只要实现了接口定义的所有方法,就被认为是实现了该接口。接口可以实现多态性,使得代码更加灵活、可扩展。
通道(Channel)是Goroutine之间进行通信的管道。通过通道,可以在不同的Goroutine之间传递数据。通道有两种类型:无缓冲通道和有缓冲通道。无缓冲通道用于同步信号的传递,发送和接收操作会阻塞直到另一方准备好;有缓冲通道可以缓存一定数量的元素,发送操作只有在通道缓冲区满时才会阻塞。
协程(Goroutine)是Go语言并发编程的执行体。通过关键字go可以创建并发执行的协程,每个协程都有自己独立的栈空间。协程由Go语言的调度器进行管理,可以在不同的逻辑处理器上进行调度,实现并发执行的效果。
锁(sync.Mutex)是一种同步机制,用于保护共享资源的访问。通过加锁,可以确保在同一时刻只有一个协程可以访问共享资源,避免并发访问导致的数据竞争问题。在互斥锁的保护下,只有获得锁的协程才能执行临界区的代码,其他协程需要等待锁的释放。
WaitGroup是Go语言中的一种同步原语,用于等待一组协程的结束。WaitGroup可以用于协程之间的同步,当所有的协程都执行完毕后,主协程可以继续执行后续的操作。
以上是关于Go语言中更多的基础知识介绍
deferr 是Go语言中的一个关键字,用于延迟执行函数调用。当一个函数使用defer关键字调用另一个函数时,被调用的函数不会立即执行,而是在包含它的函数执行完毕后再执行,例子如下: func mian() { for i := 0 ; i<3; i++ { defer func() { println(i) } } }
// 该函数最终的输出为: // 3 // 3 // 3
切片
a[:i] a[i:]
a[:i] 表示从切片开头到索引位置 i(不包括索引 i)的元素。这部分代码获取了需要保留的元素部分。
a[i+1:] 表示从索引位置 i+1 开始(包括索引 i+1),切取到切片 a 的末尾的元素。
函数 函数和操作对象的类型紧密地绑定在一起 // 关闭文件 func (f *File) CloseFile() error { // ... } // 读文件数据 func (f *File) ReadFile(offset int64, data []byte) int { // ... } 我们可以给任何自定义类型添加一个或多个方法 每种类型对应的方法必须和类型的定义在同一个包中,因此 是无法给int这类内置类型添加方法的(因为方法的定义和类型的定义不在一个包中)。对于给定的类型, 每个方法的名字必须是唯一的,同时方法和函数一样也不支持重载。
接口 --interface
Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
Go的接口类型是对其它类型行为的抽象和概括;因为接口类型不会和特定的实现细节绑定在一起,通过这种抽象的方式我们可以让对象更加灵活和更具有适应能力。很多面向对象的语言都有相似的接口概念,但Go语言中接口类型的独特之处在于它是满足隐式实现的鸭子类型。 所谓鸭子类型说的是:只要走起路来像鸭子、叫起来也像鸭子,那么就可以把它当作鸭子。Go语言中的面向对象就是如此,如果一个对象只要看起来像是某种接口类型的实现,那么它就可以作为该接口类型使用。
就比如说在c语言中,使用printf在终端输出的时候只能输出有限类型的几个变量,而在go中可以使用fmt.Printf,实际上是fmt.Fprintf向任意自定义的输出流对象打印,甚至可以打印到网络甚至是压缩文件,同时打印的数据不限于语言内置的基础类型,任意隐士满足fmt.Stringer接口的对象都可以打印,不满足fmt.Stringer接口的依然可以通过反射的技术打印。
提倡通过通信共享内存而不是通过共享内存而实现通信 Goroutine是go并发的执行体。 Channel--通道是一个Goroutinue到另一个Goroutinue的通信的机制
make (chan 元素类型,[缓冲区大小]) -无缓冲区通道 make(chan int) /也称为同步通道 -有缓冲区通道 make(chan int,2)
例子:
func main() {
src := make(chan int)
dest := make(chan int, 2)
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
go func() {
defer close(dest)
for i := range src {
dest <- i * i
}
}()
for i := range dest {
println(i)
}
}
协程
func hello(i int) {
println("Hello goroutine : " + fmt.Sprintf("%d", i)) //println--内置函数
}
func main() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
锁 lock sync.Mutex
WaitGroup
func hello(i int) {
println("Hello goroutine : " + fmt.Sprintf("%d", i)) //println--内置函数
}
func main() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}