2021/9/19 老男孩带你21周搞定Go语言 (六)

P88 今日内容

go的优势就在于并发
在这里插入图片描述

P89内容回顾

go语言的日期要记住,2006-01-02 13:04:05

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
还有after和before
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
runtime.caller可以获取到运行时的堆栈信息
在这里插入图片描述
接口类型的变量底层分为两部分:动态类和动态值。
反射的应用,可以解析json,xml各种数据解析,还有orm框架。
反射的两个方法:reflact.Typeof得到动态类型的信息,reflact.valueof动态值类型

在这里插入图片描述

把字符串解析到student的结构体
在这里插入图片描述
unmarshall参数是空接口,可以接收任何类型的值,然后反射去把对应字段解析
在这里插入图片描述

在这里插入图片描述

P90 ini配置文件解析1

在这里插入图片描述
在这里插入图片描述
可以试试map类型,读取特定字符串,值存入到相应的字段里
在这里插入图片描述
读文件,读出字节类型的数据
在这里插入图片描述
ptr就是指针
在这里插入图片描述

在这里插入图片描述
返回的是一个error类型

在这里插入图片描述
格式化输出后返回一个error类型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
t是指针类型,elem拿到值,等于先判断是不是指针,再判断是不是结构体
在这里插入图片描述
make初始化只针对slice,map,channel,剩下都是new,new是给值类型做初始化的。必须是要一个结构体指针,传一个int类型的指针是不行的
在这里插入图片描述
换成结构体指针就没问题了在这里插入图片描述
读文件,ioutil,数据保存到一个变量,然后按照换行符切割。
在这里插入图片描述
在这里插入图片描述

P91 init配置解析2

配置文件读取出来放到了一个slice里

在这里插入图片描述
一行行读数据,遇到注释的就跳过。如果[开头就是段落section,把【】去掉,读取下面的内容
在这里插入图片描述
提示这里有语法错误
在这里插入图片描述
现在格式没问题,就没有语法错误了
在这里插入图片描述
获取字段名,并在相应data里根据反射找对应的结构体,造一个结构体的嵌套,找到mysql对应的结构体,再从对应结构体里找不同的字段
在这里插入图片描述
结构体名字接收变量
在这里插入图片描述

for循环遍历拿到数据里的值,找到对应的mysql段落还是其他段落
在这里插入图片描述使用指针
在这里插入图片描述
如果走到了【】段落名,那就跳出循环,读取该段落的配置字段了,
1.也就是以等号分割这一行,等号左边是key,右边是value。(不规范的要去掉,提示语法错误)
2.根据structname去data里面把对应的嵌套结构体给取出来。
3.遍历嵌套结构体的每一个字段,判断tag是不是等于key。
4.如果是key=tag,给这个字段 赋值

在这里插入图片描述
空行跳过
在这里插入图片描述
这样就没问题了

在这里插入图片描述
根据struct name去data里把对应的字段值取出来
在这里插入图片描述
先把key拿出来,切到等于号,key就是address,value就是后面的ip地址。
在这里插入图片描述
遍历嵌套结构体字段,判断tag是不是等于key
在这里插入图片描述
下面拿到的值也需要稍微改动,等于key就找到了对应的字段
在这里插入图片描述
第四步,赋值
在这里插入图片描述
在这里插入图片描述
把值存起来

在这里插入图片描述
在这里插入图片描述
找到对应字段就退出
在这里插入图片描述
在这里插入图片描述
下面判断obj,reflact如果是一个string,就设置成string
在这里插入图片描述
这里字符串就都有了
在这里插入图片描述
字符串有了,加个int类型,那就涉及到把之前string类型的数字转成int类型
在这里插入图片描述
可以使用strconv.parseint,转几进制数,多少位,返回int64和err
在这里插入图片描述
10进制数,64位,现在parseint还有问题
在这里插入图片描述
解析错误,17行有问题
在这里插入图片描述

xxx这里应该找不到字段,就直接跳过了,没有必要赋值

在这里插入图片描述
port的值类型错误。
在这里插入图片描述
现在就都加载出来了
在这里插入图片描述
在这里插入图片描述
判断float
在这里插入图片描述
添加一个test布尔值
在这里插入图片描述
流程:从配置文件读取出,把数据依次赋值到结构体里,利用反射一个字段一个字段去找,根据结构体tag值找到key值,
在这里插入图片描述
所有配置文件解析,go语言里都是做map的

在这里插入图片描述
也有现成的ini库
在这里插入图片描述

P92 strconv标准库介绍

go是强类型语言,类型和类型之间不能互相转换,支持强制转换的前提是支持转换的,int64转int32,数字和字符串类型就不能互相转了。

数字当作ascii码了,拿编码找到了这个字符
在这里插入图片描述
在这里插入图片描述
拿到字符串的97,直接string(),是用数字做一个utf-8编码了,去找对应符号去了
在这里插入图片描述

还有一个方法,strconv.parseint,字符串转int
在这里插入图片描述
这样1000这个字符串就转成int64了,前面的10代表10进制

在这里插入图片描述
10,0,传0的话就是int类型,但返回值定死了,就是int64
在这里插入图片描述这样就返回int

在这里插入图片描述
但是转成int一般不用上面的,Atoi就是字符串转成int
在这里插入图片描述
数字转换成字符串Itoa
在这里插入图片描述
strconv是把对应的字符传解析成需要用的数据,比如boolstr
在这里插入图片描述

P93 并发编程介绍

java做并发,需要os里线程池,包装一下,起一个线程,执行完再关闭,这里os线程运行的时候会遇到上下文切换,一个线程最起码要2M。
go里实现了自己的线程,goroutine,切换的时候是自己切。
并发代表同一段时间 内执行多个任务。
并行代表同一时刻执行多个任务。
go的并发用goroutine实现。等于在cpu阻塞的时候去做其他的事情。类似于线程,但是是属于用户态的线程。
goroutine是由go语言的运行时runtime调度完成的。
channel是在用多个goroutine进行通信的,协调工作用的。

在这里插入图片描述

P94 创建goroutine

在这里插入图片描述
在调用函数的时候前面加上go 关键字,就能实现并发。
在这里插入图片描述
在这里插入图片描述
**
程序启动之后会创建一个主goroutine去执行,go关键字代表开启一个单独的goroutine去执行hello函数(任务)**
在这里插入图片描述
现在打印一个main,main函数结束,由main函数启动的goroutine也都结束了
在这里插入图片描述
会停顿一下在这里插入图片描述
打印多个,打印的时候顺序不一定
在这里插入图片描述

P95 sync.WaitGroup

改造成匿名函数,为什么有3个999,打印i这个变量,这个变量是在外面拿的,启动一个go routine的 时候,可能for循环转的够快,已经走了好几个循环了,所以打印的时候出现了多个。
在这里插入图片描述
可以在函数执行的时候把参数传进去,这样每个for循环就把值主动 传进去了。说明启动goroutine是要消耗时间和资源的。
在这里插入图片描述

**优雅方式等待goroutine去结束,sync包里有一个Waitgroup
**
在这里插入图片描述
goroutine对应的函数执行结束了,gocroutine才结束
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
程序编译好了,每次执行的都一样,赋值进去了,每次执行都是一样的
在这里插入图片描述
1970年到现在的纳秒数,这样肯定是不一样的,这样 写的程序的随机数就没问题
在这里插入图片描述

在这里插入图片描述
struct是值类型

在这里插入图片描述

done代表计数器结束了

在这里插入图片描述
通常这么写,确保done了

在这里插入图片描述

启动10个goroutine

在这里插入图片描述
等待计数器减为0就退出,3可能还没来得及输出就退出了

在这里插入图片描述
等待时间 长点就可以看到3了
在这里插入图片描述

sync.waitgroup可以同步多个goroutine退出才退出

在这里插入图片描述

P96 goroutine调度模型GMP

goroutine是用户态的线程 ,是go语言自己实现的类似线程的东西。
goroutine和线程 的区别就是栈不一样 。os线程一般都固定栈的内存是2M,一个goroutine的栈不是固定的,最小2Kb,最大1GB。
所以go语言中可以一次创建十万作用的goroutine也是可以的。

在这里插入图片描述
goroutine调度,GMP调度
G:就是goroutine,里面除了存放本goroutine信息外还有与所在ip的绑定等信息。
M:machine 是Go运行时对操作系统内核线程的虚拟,M与内核线程一般是映射关系,一个gorutine最终是要放到M上执行的。
P:管理一组goroutine队列,P里面会存储当前goroutine运行的上下文环境(函数指针,堆栈地址及地址边界),P会对自己管理的goroutine队列做一些调度(比如把占用cpu时间较长的goroutine暂停、运行后续的goroutine等等)当自己的队列消费完了就去全局队列里重取,如果全局队列里也消费完了会去其他P的队列里抢任务。

在这里插入图片描述
当io阻塞的时候 ,就会切换。p的个数是通过runtime.GOMAXPROCS设定,最大256,go1.5版本之后默认为物理线程数,在并发量打的时候会则更加一些P和M,但不会太多。
所有都是p调度的,也就是go语言自己调度,比其他语言用操作系统调度,就省很多资源。把m个goroutine放到一个操作系统线程上进行工作。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
windows无效,体会不出来,先试个1核
在这里插入图片描述
先打印B再打印A

在这里插入图片描述
多核可能会出现打印错乱的情况
在这里插入图片描述
默认就是cpu的核心数
在这里插入图片描述
操作系统启动的是进程,但是真正干活的是线程

在这里插入图片描述

操作系统线程核goroutine的关系:
1个操作系统线程对应用户多个goroutine
go程序同时可以有多个操作系统编程。
goroutine核OS线程是多对多关系。

在这里插入图片描述

goroutine调度模型,GMP
G是goroutine
M是用于和操作系统线程做映射的。
P是管理goroutine,阻塞的时候进行切换

在这里插入图片描述

P97 channel初识

单纯让函数起一个goroutine没有意义,肯定是中间有多个环节进行交互。
现在不是使用共享内存来实现数据通信(这样会数据加锁,并行变串行)而是通过通信,实现共享内存。go语言用通道实现多个goroutine通信的。
goroutine是go语言并发的执行体,channel相当于做链接。channel是一个特殊类型,类似传送带,遵循先入先出

在这里插入图片描述
在这里插入图片描述需要指定通道中元素的类型,channel是一个引用类型,需要初始化去使用,分配内存使用。
在这里插入图片描述
make,初始化slice,map,channel
在这里插入图片描述
在这里插入图片描述
带缓冲区和不带缓冲区,满了的话有人接才能放
在这里插入图片描述
channel的使用有三种操作,发送,接收,关闭

在这里插入图片描述
在这里插入图片描述
不管发送还是接收,都是用<小于号
在这里插入图片描述
发送是从goroutine到channel,接收是从channel到goroutine

在这里插入图片描述
相当于卡在这里了
在这里插入图片描述
等于永远放不进去,现在是一个main的一个goroutine

在这里插入图片描述
可以再起一个匿名函数试试
在这里插入图片描述
在这里插入图片描述
使用sync.waitgroup等待goroutine结束
在这里插入图片描述
现在就打印出来了
在这里插入图片描述
下面的放进去,上面的才能取出来

在这里插入图片描述
没有缓冲区的channel
在这里插入图片描述
带缓冲区的channel,初始化里,里面最多存一个容量,所以下面就可以放进去

在这里插入图片描述
在这里插入图片描述
取值
在这里插入图片描述
只有1个容量,所以,下面的就卡住了
在这里插入图片描述
关闭close掉
在这里插入图片描述
箭头代表数据的流向

在这里插入图片描述
在这里插入图片描述
如何优雅地从通道循环取值
在这里插入图片描述
forange也支持从通道取值
在这里插入图片描述

P98 channel练习

先造100个数放到通道1,另外的goroutine从通道1取值,每个乘平方,然后把结果放到通道2里。

在这里插入图片描述
f1循环放值,f2循环取值
在这里插入图片描述
最后读不到数据,会返回一个false,只要不关闭,一直都是true

在这里插入图片描述
这个数就算出来了
在这里插入图片描述
在这里插入图片描述
sys.once只执行一次

在这里插入图片描述
once确保某个操作只执行一次,只关闭一次
在这里插入图片描述
在这里插入图片描述
关闭通道的时候,如果原来有值,读会继续读,之后返回值是false
在这里插入图片描述
对一个关闭通道继续取值,是可以取的,只不过会是false

在这里插入图片描述
在这里插入图片描述
关闭的通道取多少次都是false,bool是false,字符串就是为空

在这里插入图片描述

P99 单向通道

单向通道一般用在函数的参数里,限制别人只想发送什么,或接收什么。确保暴露出去的通道只能有一项操作。限制你一个函数里只能往ch2里放进去,不能取出来。
在这里插入图片描述
返回的是一个通道,通道类型是时间类型。单向通道,只能从里面去读取。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
channel三种操作,接收发送,关闭。
通道状态,nil,非空,空的,满了,没满。
nil没有初始化的时候,接收,发送都是阻塞的,关闭会panic,关闭已经关闭的会panic。
如果主程序一直运行,后面goroutine一直占内存,永远不可能把内存释放,这是goroutine泄露

在这里插入图片描述

P100 work_pool练习

goroutine池,work_pool这种模式

在这里插入图片描述
在这里插入图片描述
造三个goroutine去执行任务
在这里插入图片描述
在这里插入图片描述
worker是包装了一个任务,id是int,jobs是一个只读的通道,result是只写的通道。
从只读通道取值,算乘2 的值

在这里插入图片描述
起三个goroutine,5个任务

在这里插入图片描述
id为3的goroutine先起5个任务

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
开启一个goroutine循环加入job
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

从job取数,计算合,发送到result
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

打印数
在这里插入图片描述

P101 select介绍

从多个通道去取,叫多路复用。
想要实现每次随机从c1或者c2里取

在这里插入图片描述
c1取不到到c2里取,c2取不到到c1里取

在这里插入图片描述
select,多个case满足,可以随机选一个
在这里插入图片描述
这样每次执行结果都不一样

在这里插入图片描述
在这里插入图片描述

P102 作业要求

之前的日志是同步写的,可以起一个goroutine,日志放到channel里,一直从channel里拿日志写文件。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值