Golang

来自智得网
跳转至: 导航、​ 搜索

简介

golang最早是google公司设计的一门开源语言,这门语言主要面向工程实践。

原理

协程

线程协程的调度机制

协程是为了节约线程的内存占用以及上下文切换成本而推出的用户态线程,和进程/线程相比,协程更加轻量级。

进程/线程是由操作系统分配并且调度的,进程有单独的地址空间,有独立上下文,不同线程可以同享进程的地址空间以及资源,进程和线程都由操作系统调度,但是协程是用户态实现的类线程资源,由用户态完成调度,所以协程的调用栈比进程/线程更小,线程的调用栈一般是1M~10M,而协程一般仅1K~50K,而且用户态调度可以节约用户态和内核态切换,调度成本更小。

地址空间 调度方 调度方式
进程 独立地址空间 操作系统内核 时间片,中断,系统调用
线程 进程创建的所有线程共享进程地址空间 操作系统内核 时间片,中断,系统调用
协程 同一Golang进程内的协程共享地址空间 用户态 中断,抢占,主动出让

协程和线程/进程底层调度逻辑不同点主要如下:

  • 协程调度不需要操作系统介入,是用户态来实现调度逻辑的,本质上Golang的协程框架实现了调度功能。
  • 协程调度的时机一般发生在IO等需要阻塞的阶段,Golang的协程框架需要监听此类时间。
  • 使用协程时候,IO机制一般使用异步机制。

GMP

GMP是golang中协程的调度机制。

GC

切片

一般编程语言的数组都是静态大小的,由列表等数据结构提供动态大小的线性数据结构。但是Golang语言提供了可以自动扩容的动态数组——切片(Slice),切片支持追加,遍历,截取、随机访问等能力。

Golang也提供数组类型的数据结构,数组是长度是不可变化的,需要在声明数组的时候确定的长度的值,一般是传入明确的数组长度或者通过数组的值而确定数组的长度。

切片的声明和数组类似,但是不需要传入切片的长度,或者通过make方式构建,此时传入一个初始长度。

// 定义数组
array1 := [10]int{}
array2 := [...]int{1,2,3,4,5}
var array3 [7]float32

// 定义切片
var slice1 []int
var slice2 := make([]int, 5)
slice3 := []int{1, -1  ,0,  1, 4}

// 二维切片定义,需要分别初始化二维切片和每一项一维切片
row, column := 3, 4
var matrix [][]int
for i := 0; i < row; i++ {
   inline := make([]int, column)
   matrix = append(matrix, inline)
}
切片不能使用“==”进行比较,所以切片不能作为map结构的Key。

使用

安装

语法

基本类型

生态

工具
Pprof生成的火焰图

Golang集成了性能调试(Profiling)的工具pprof,Profiling是指在程序运行过程中动态收集程序运行时数据的一种程序分析方法。

Golang语言的pprof库支持对CPU、Heap、Goroutine、Mutex、Thread、Block等6种资源的采样。

pprof使用方式支持API调用采样、命令行调用采样,以及后台采样。后台采样封装了Http Server,可以对外展示可视化的Profiling信息。

pprof的结果是以火焰图的方式展示,其中又分为普通火焰图以及差分火焰图。

火焰图(Flame Graph)是由Brendan Gregg发明的一种profile数据可视化工具。

X 轴表示函数采样数,如果一个函数在 X 轴占据的宽度越大,就表示它被采样到的次数越多,可以反映出来该函数执行时间较长。

Y轴表示调用栈,每一层都是一个函数。火焰就越高说明调用栈就越深,底部是正在执行的函数,上方都是调用方。