本文内容纲要:
goroutine(协程)&& channel(管道)
使用并发或者并行的方式,CPU
线程和进程说明
- 进程就是程序在操作系统中的一次执行过程中,是系统进行资源分配和调度的基本单位。
- 线程是进程的一个执行实例,是程序执行的最小单元,它是比进程更小的能独立运行的基本单位。
- 一个进程可以创建和销毁多个线程,同一个进程中的多个线程可以并发执行
- 一个程序至少有一个进程,一个进程至少有一个线程
并发和并行的区别
- 1)多线程程序在单核上运行,就是并发
-
- 多线程在多核上运行,就是并行
go的协程和go的主线程
- 1)go主线程(有程序员直接称为线程/也可以理解成进程):一个go线程上,可以起多个协程。 可以这样理解,协程是轻量级的线程
- 2)go协程的特点
2.1. 有独立的栈空间
2.2. 共享程序堆空间
2.3. 调度由用户控制
2.4. 协程是轻量级的线程
goroutine
- 主线程是一个物理线程,直接作用在cpu上,是重量级的,非常耗费CPU资源。
- 协程从主线程开启的,是轻量级的线程,是逻辑态。对资源消耗相对小。
- golang的协程机制是重要的特点,可以轻松的开启上万个协程,其他编程语言的开发机制是一般基于线程的,开启过多的线程,
资源耗费大,这里就凸显golang在并发上的优势了。
为什么需要channel
- 主线程在等待所有goroutine全部完成的时间很难完成,我们这里设置10秒,仅仅是估算。
- 如果主线程休眠时间长了,会加长等待时间,如果等待时间短了,可能还有goroutine处于工作状态,这时也会随主线程的退出而销毁
- 通过全局变量加锁同步来实现通讯,也不利用多个协程对全局变量的读写操作,
- 上面种种分析都在呼唤一个新的通讯机制 channel
channel介绍
- channel本质就是一个数据结构-队列
- 数据是先进先出
- 线程安全,多goroutine访问时,不需要加锁,就是说channel本身就是线程安全的。
- channel时有类型的,一个string的channel只能存放string类型的数据。
channel 管道-基本使用
var 变量名 chan 数据类型
说明
- channel是引用类型
- channel必须初始化才能写入数据,即make后才能使用
- 管道是有类型的,intChan只能写入数据int
channel 管道注意事项
- channel中只能存放指定的数据类型
- channel的数据放满后,就不能再放入了
- 如果从channel取出数据后,可以继续放入
- 在没有使用协程的情况下,如果channel数据取完了,再取就会报dead lock
channel 的遍历和关闭
使用内置函数close可以关闭channel,当channel关闭后,就不能再向channel写数据了,但是仍然可以从该channel读取数据
channel的遍历
channel支持for-range的方式进行遍历,遍历细节
- 1)在遍历时,如果channel没有关闭,则会出现deadlock的错误
-
- 在遍历是,如果channel已经关闭,则会正常遍历数据,遍历完后,就会退出遍历。
- 默认情况下,管道是双向的。
- 声明为只写 , 声明为只读
- 使用select可以解决从管道取数据的阻塞问题。
- goroutine中使用recover,解决协程中出现panic,导致程序崩溃问题。
反射 tag 解决序列化key的名字
基本介绍
7. 反射可以在运行时动态获取变量的各种信息,比如变量的类型type,类别
8. 如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段,方法)
9. 通过反射,可以修改变量的值,可以调用关联的方法
10. 使用反射,需要import (“reflect")
11. 变量、interface{}、和reflect.Value是可以相互转换的。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 常量使用const修改
- 常量在定义的时候,必须初始化
- 常量不能修改
- 常量只能修饰bool、数值类型(int、float系列)、string类型
- 语法 const identifier [type] = value
举栗子: const name = “tome”
const tax float64 = 0.8 - go 中没有常量名必须字母大写的规范
- 仍然通过首字母的大小写来控制常量的访问范围。
反射的注意事项和细节
- reflect value kind 获取变量的类别,返回的是一个常量
- Type和kind的区别 :type是类型,kind是类别,type和kind可能相同,也可能是不相同的
- 通过反射可以让变量在interface和refleact.value之间相互转换,
- 使用反射的方式获取变量的值(并返回对应的值)要求数据类型匹配,比如x是int,name就应该使用reflect.Value(x).int 而不能使用其它的,否则报panic
- 通过反射的修改变量,注意当使用setxx方法来设置需要通过对应的指针类型来完成,这样才能改变传入的变量的值,同时需要使用到reflect.Value.Elem()的方法。
- reflect.Value.Elem()
本文内容总结: