go 语言入门指南:基本语法和常用特性解析1|青训营

64 阅读3分钟

go 语言入门指南:基本语法和常用特性解析

一.协程 goroutine

goroutine的引入,从一个需求出发。需求:要求统计1-900000000000的数字中,哪些是素数?

分析思路: 1)传统的方法,就是使用一个循环,循环的判断各个数是不是素数。(很慢的) 2)使用并发或者并行的方式,将统计素数的任务分配给多个goroutine去完成,这个时候可以使用到goroutine

goroutine的基本介绍

进程和线程的区别

1)进程就是程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位。

2)线程是进程的一个执行实例,是程序执行的最小单元,它是比进程更小的能独立运行的基本单元。

3)一个进程可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行

4)一个程序至少有一个进程,一个进程至少有一个线程

并发和并行

1)多线程程序在单核上运行,就是并发

2)多线程程序在多核上运行,就是并行

并发:因为是在一个cpu上,比如有10个线程,每个线程执行10毫秒(进行轮询操作),从人的角度看,好像这10个线程都在运行,但是从微观上看,在某一个时间点看,其实只有一个线程在执行,这就是并发。

并行:因为是在多个CPU上(比如8个CPU),比如有8个线程,每个线程执行10毫秒(各自在不同的CPU上执行),从人的角度看,这8个线程都在运行,但是从微观上看,在某一个时间点看,也同时有8个线程在执行,这就是并行。

GO协程和Go主线程

1)Go主程序(有程序员直接称为线程/也可以理解为进程);一个Go线程上,可以起多个协程,也可以这样理解,协程是轻量级的线程(编译器做优化)。

2)Go协程的特点

  1. 有独立的栈空间
  2. 共享程序堆空间
  3. 调度由用户控制
  4. 协程是轻量级的线程

goroutine-快速入门

案例:在主线程(可以理解为进程)中,开启一个goroutine,该协程每隔1s输出"hello,world".在主线程中每隔1s输出"hello golang",输出10s后,退出程序。要求主线程与goroutine同时执行

代码实现:

package main  
  
import (  
"fmt"  
"strconv"  
"time"  
)  
  
//编写函数 每隔1s输出 “hello,world”  
  
func test() {  
    for i := 1; i <= 10; i++ {  
    fmt.Println(" test() hello,world" + strconv.Itoa(i))  
    time.Sleep(time.Second)  
    }  
}  
  
func main() {  
go test() //开启了一个协程  
    for i := 1; i <= 10; i++ {  
    fmt.Println(" main() hello,golang" + strconv.Itoa(i))  
    time.Sleep(time.Second)  
}  
}

输出的效果是:main这个主线程和test协程同时执行

image.png 主线程和协程的执行示意图:

image.png

快速入门小结:

1) 主线程是一个物理线程,直接作用在CPU上的,是重量级的,非常耗费cpu资源。

2)协程从主线程开启的,是轻量级的线程,是逻辑态,对资源消耗相对小。

3)Golang的协程机制是重要的特点,可以轻松的开启上万个协程。其他编程语言的并发机制一般是基于线程的,开启过多的线程,资源消耗大,这里就突显Golang在并发上的优势了。

goroutine的调度模型

MPG模式基本介绍

1)M:操作系统的主线程(是物理线程) 2)P:协程执行需要的上下文 3)G: 协程

设置Golang运行的cpu数

介绍:为了充分利用多cpu的优势,在Golang程序中,设置运行的cpu数目

package main  
  
import (  
"fmt"  
"runtime"  
)  
  
func main() {  
    //获取当前系统的CPU数目  
    num := runtime.NumCPU()  
    runtime.GOMAXPROCS(num)  
    fmt.Println("num=", num)  
  
}

go1.8以后,默认让程序运行在多个核上,可以不用设置了。go1.8前,还是要设置一下,可以高效的利用cpu