Go从入门到进阶,大厂案例全流程实践「有讠果」

164 阅读3分钟

Go从入门到进阶,大厂案例全流程实践

核心代码,注释必读

// download:3w ukoou com

Go复合类型类型

数组

数组顾名思义就是同一类资源或者数据的集合。下面主要介绍对数组的操作:

数组的初始化

var arr [3]int  //默认初始化0
var q [3]int = [3]int{1,2,3}
q := [...]int{1,2,3}
q := [...]int{90:-1}//key和value的赋值方式,下表90的值为-1,数组长度为91

数组的访问

可以使用数组下标来访问数组中的元素。与C语言相同,数组下标从0开始,len(array)-1 则表示最后一个元素的下标。下面的示例遍历整型数组并逐个打印元素内容:

q := [...]int{1, 2, 3, 4}
for i, value := range q {
    fmt.Println(i, value)
}

数组可以直接进行比较,当数组内的元素都一样的时候表示两个数组相等。

arr1 := [3]int{1, 2, 3}
arr2 := [3]int{1, 2, 3}
arr3 := [3]int{1, 2, 4}    
fmt.Println(arr1 == arr2, arr1 == arr3)  //true,false

数组可以作为函数的参数传入,但由于数组在作为参数的时候,其实是进行了拷贝,这样在函数内部改变数组的值,是不影响到外面的数组的值得。

func ArrIsArgs(arr [4]int) {
    arr[0] = 100
}
q := [...]int{1, 2, 3, 4}
ArrIsArgs(q)

如果想要改变:

func ArrIsArgs(arr *[4]int) {
    arr[0] = 100
}
q := [...]int{1, 2, 3, 4}
ArrIsArgs(&q)

但一般都是用切片来解决这个问题,而不是用数组。

Go从入门到进阶,大厂案例全流程实践 - 使用channel来实现协程间的信息同步

通过channel,能够确保一个协程在另一个协程完成工作之后才能继续。如果需要在两个或多个协程之间共享数据的场景中,这种用法就特别有用,并且能够确保数据不会同时被多个协程修改非常重要。

我们先看一个简单的示例:

package main

import (
    "fmt"
    "time"
)

func worker(done chan bool) {
    fmt.Print("working...")
    time.Sleep(time.Second)
    fmt.Println("done")

    done <- true
}

func main() {
    done := make(chan bool, 1)
    go worker(done)

    <-done
}

复制

在这个示例中,我们创建了一个worker协程,同时在main协程中创建了一个done通道。当worker协程完成工作后,往done通道中发送了一个true,代表通知main协程worker执行完毕了。

开源项目中的应用

接下来我们看几个开源项目中的示例。

应用一:利用通道进行平滑关闭

在gin框架的example中,有一个关闭服务的示例,就是利用了通道来在两个协程间进行通讯的特性。如下:

这里就是在main协程中创建了一个quit通道,然后并将该quit通道传递给signal.Notify函数,然后通过<-quit阻塞等待signal.Notify函数执行完毕。在signal.Notify中其实是注册并监听syscall.SIGTERM信号,通过启动了一个新的协程来监听该信号。当该信号发生时,就往quit通道中写入一个os.Signal的数据。

应用二:fastcache中利用通道输出结果

在fastcache开源项目中,有个功能是将数据保存到文件中。在保存函数中用到了并发保存,同时需要将每个保存的结果输出。下面就是通过通道来接收每个协程的保存结果的功能。如下: