Go基础知识梳理(四)

GO的哲学是“不要通过共享内存来通信,而是通过通信来共享内存”,通道是GO通过通信来共享内存的载体。

rumtime包常用方法

runtime.NumGoroutine() //返回当前程序的协程数量
runtime.GOMAXPROCS(0) //获取当前的GOMAXPROCS数量
runtime.GOMAXPROCS(2) //设置程序的GOMAXPROCS数量为2

goroutine

特性

  • 执行是非阻塞的,不会等待
  • go 后面的返回值会被忽略
  • 调度器不能保证goroutine的执行顺序
fun main() {
//另起一个协程去打印
go func() {
fmt.Println("goruntine")
}()
}

chan

//创建chan
c := make(chan dataType)
//无缓冲, len 和 cap 都是0
fmt.Println(len(c)) //0
fmt.Println(cap(c)) //0 //有缓冲
c = make(chan dataType, 10)
//len 代表没有被读取的元素数, cap 代表整个通道的容量
fmt.Println(len(c)) //0
fmt.Println(cap(c)) //10

WaitingGroup组件

Add(10) 给内置计数器加10

Done() 相当于Add(-1)

Wait() 内置计数器不为0则一直等待

// 写法
func main() {
var wg sync.WaitGroup
wg.Add(10)
for i := 0; i < 10; i++ {
go func(i int) {
defer wg.Done()
fmt.Println(i)
time.Sleep(time.Millisecond * 3000)
}(i)
}
wg.Wait()
fmt.Println("done")
}

select

  1. 先打乱所有的case语句
  2. 遍历case语句,查看是否已经读写了
  3. 选择可读写的case去执行
  4. 没有可读写的case,则查看default语句是否定义,再去执行
  5. 没有defaul语句,则会等待可执行的case

看一段融合了并发,缓冲,退出通知等多重特性的代码

func GenerateA(done chan struct{}) chan int {
ch := make(chan int, 5)
// fmt.Println("通道数+1")
go func() {
fmt.Println("线程数+A")
Label:
for {
select {
case res := <-done:
fmt.Println("done", res)
break Label
case ch <- rand.Int():
} }
close(ch)
}()
return ch
}
func GenerateB(done chan struct{}) chan int {
ch := make(chan int, 5)
go func() {
fmt.Println("线程数+B")
Label:
for {
select {
case res := <-done:
fmt.Println("done", res)
break Label
case ch <- rand.Int():
}
}
close(ch)
}()
return ch
} func GenerateInt(done chan struct{}) chan int {
//无缓冲通道
ch := make(chan int)
send := make(chan struct{})
go func() {
Label:
for { select {
case <-done:
send <- struct{}{}
send <- struct{}{}
break Label
case ch <- <-GenerateA(send):
fmt.Println("chose A")
case ch <- <-GenerateB(send):
fmt.Println("chose B")
}
}
close(ch)
}()
return ch
} func main() {
done := make(chan struct{})
ch := GenerateInt(done)
fmt.Println(runtime.NumGoroutine())
for i := 0; i < 10; i++ {
fmt.Println(<-ch)
}
fmt.Println(runtime.NumGoroutine())
done <- struct{}{}
fmt.Println("stop gernate", struct{}{})
time.Sleep(1 * time.Second) //等待1s,让停止的goruntime打印,如果不加这句话,可能会导致主线程比新起的协程早退出,从而无法打印出done {}
}

打印结果不展示,其中发现的问题:

1.打印出来的数字长度不固定

2.每次Select查看case是否堵塞的时候,都会执行一次该方法

Context

func main() {
ctxa, cancel := context.WithCancel(context.Background())
go work(ctxa, "work1")
tm := time.Now().Add(3 * time.Second)
ctxb, _ := context.WithDeadline(ctxa, tm)
go work(ctxb, "work2")
oc := OtherContext{ctxb}
ctxc := context.WithValue(oc, "key", "andes, pass from main")
go workWithValue(ctxc, "work3")
time.Sleep(10 * time.Second)
cancel()
time.Sleep(5 * time.Second)
fmt.Println("main stop") } type OtherContext struct {
context.Context
} func work(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
fmt.Printf("%s get msg to cancel\n", name)
return
default:
fmt.Printf("%s is running \n", name)
time.Sleep(1 * time.Second)
}
}
} func workWithValue(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
fmt.Printf("%s get msg to cancel\n", name)
return
default:
value := ctx.Value("key").(string)
fmt.Printf("%s is running value=%s \n", name, value)
time.Sleep(1 * time.Second)
}
}
}

这段代码中,都是一条链路下来的

根节点 context.Background() -> ctxa -> ctxb -> oc

其中ctxa加了个时间控制,所以到达一定的时间就会自动关闭

oc附带了个键对值

Go基础知识梳理(四)的更多相关文章

  1. [SQL] SQL 基础知识梳理(四) - 数据更新

    SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...

  2. [SQL] SQL 基础知识梳理(一)- 数据库与 SQL

    SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...

  3. [SQL] SQL 基础知识梳理(三) - 聚合和排序

    SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...

  4. [SQL] SQL 基础知识梳理(五) - 复杂查询

    SQL 基础知识梳理(五) - 复杂查询 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5939796.html 序 这是<SQL 基础知识梳理( ...

  5. C#基础知识梳理索引

    C#基础知识梳理索引 一 引子 之前曾写了一篇随笔<.NET平台技术体系梳理+初学者学习路径推荐+我们的愿景与目标> 三个月过去了,目标使更多的编程初学者,轻松高效地掌握C#开发的基础,重 ...

  6. [SQL] SQL 基础知识梳理(六)- 函数、谓词、CASE 表达式

    SQL 基础知识梳理(六)-  函数.谓词.CASE 表达式 目录 函数 谓词 CASE 表达式 一.函数 1.函数:输入某一值得到相应输出结果的功能,输入值称为“参数”,输出值称为“返回值”. 2. ...

  7. [SQL] SQL 基础知识梳理(七)- 集合运算

    SQL 基础知识梳理(七)- 集合运算 目录 表的加减法 联结(以列为单位) 一.表的加减法 1.集合:记录的集合(表.视图和查询的执行结果). 2.UNION(并集):表的加法 -- DDL:创建表 ...

  8. Linux基础知识梳理

    Linux基础知识梳理 Linux内核最初只是由芬兰人林纳斯?托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的.Linux是一套免费使用和自由传播的类Unix操作系统,是 ...

  9. MySQL 基础知识梳理

    MySQL 的安装方式有多种,但是对于不同场景,会有最适合该场景的 MySQL 安装方式,下面就介绍一下 MySQL 常见的安装方法,包括 rpm 安装,yum 安装,通用二进制安装以及源码编译安装, ...

随机推荐

  1. %r和%s的区别

    理解%r和%s的区别 %r会重现所表达的对象,%s会将所有转成字符串 eg1: print('i am %s years old' % 22) print('i am %r years old' % ...

  2. 从服务端生成Excel电子表格(GcExcel + SpreadJS)

    在服务端生成Excel电子表格,除了使用 Node.js + SpreadJS 外,葡萄城官方推荐使用 SpreadJS + GcExcel.该方案不仅能够解决批量绑定数据源并导出Excel.批量修改 ...

  3. 阿里四面:你知道Spring AOP创建Proxy的过程吗?

    Spring在程序运行期,就能帮助我们把切面中的代码织入Bean的方法内,让开发者能无感知地在容器对象方法前后随心添加相应处理逻辑,所以AOP其实就是个代理模式. 但凡是代理,由于代码不可直接阅读,也 ...

  4. 使用ajax上传文件

    1. XMLHttpRequest(原生ajax) [](javascript:void(0) <input class="file" type="file&quo ...

  5. Python将py文件编译为exe的方法

    使用PyCharm工具写好的Python程序脚本,怎么将.py文件编译为可执行的.exe文件 前提是已经安装了Python环境. 第一步:在PyCharm内下载安装pyinstalle库或使用CMD安 ...

  6. LeetCode随缘刷题之最短补全词

    package leetcode.day_12_10; import org.junit.Test; /** * 给你一个字符串 licensePlate 和一个字符串数组 words ,请你找出并返 ...

  7. 使用haproxy的ACL实现基于文件后缀名的动静分离

    一.环境准备 二.实现proxy [root@localhost ~]# yum -y install haproxy #创建子配置 [root@localhost ~]# mkdir /etc/ha ...

  8. Sublime Python3编译环境修改

    http://blog.csdn.net/qq_33304418/article/details/63337602     添加编译环境python3.6 Tools -> Build Syst ...

  9. iOS 如何监听用户在手机设置里改变了系统的时间?

    如何监听用户未退出APP但通过Home键在手机设置里改变了系统的时间? 用户虽未退出APP,但是当它按Home键退到后台时 ,会调用该方法: - (void)applicationDidEnterBa ...

  10. 7、架构--location、LNMP架构、uwsgi部署、BBS项目部署

    笔记 1.晨考 1.Nginx中常用的模块 autoindex stub_status allow 和 deny basic limit_conn limit_req 2.配置步骤 1.创建连接池 2 ...