go基本语法学习笔记之并发编程

wolgame · · 1253 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

  GO并发

 在一个函数调用前加上go关键字,这次调用就会在一个新的goroutine中并发执行。

func Add(x, y int) {
     z := x + y
     fmt.Println(z)
}
func main() {
    for i := 0; i < 10; i++ {
            go Add(i, i)
    }
}


     Go程序从初始化main package并执行main()函数开始,当main()函数返回时,程序退出.且程序并不等待

其他goroutine(非主goroutine)结束。

并发通信

GO语言既以并发编程作为语言的最核心优势,提供了一种通信模型,即以消息机制而非共享内存作为通信方式。
消息机制认为每个并发单元是自包含的、独立的个体,并且都有自己的变量,但在不同并发单元间这些变量不共享。每个并发单元的输入和输出只有一种,那就是消息。
这有点类似于进程的概念,每个进程不会被其他进程打扰,它只做好自己的工作就可以了。不同进程间靠消息来通信,它们不会共享内存。

Go语言提供的消息通信机制被称为channel
       “不要通过共享内存来通信,而应该通过通信来共享内存。”

channel

channel是Go语言在语言级别提供的goroutine间的通信方式。channel是类型相关的

chan声明

var chanName chan ElementType
如:
var chint chan int  //什么一个int类型的chan

var mch  map[string] chan bool  //声明一个map,其元素为bool

var arrch [10]chan int //定义一个

实例

func Count(ch chan int) {
     ch <- 1
     fmt.Println("Counting")
}
func main() {
     chs := make([]chan int, 10)
     for i := 0; i < 10; i++ {
         chs[i] = make(chan int)
         go Count(chs[i])
     }
     for _, ch := range(chs) {
         <-ch
     }
}
定义channel
直接使用内置的函数make()即可:
    ch := make(chan int)
channel基本用法
写入
<span style="white-space:pre">	</span>ch < 1
向channel写入数据通常会导致程序阻塞,直到有其他goroutine从这个channel中读取数据

读出
   i := < ch
如果ch没有数据也会导致程序阻塞,直到有数据写入ch

但是,对ch的阻塞,可以利用ch的缓冲机制以及select来灵活出来

缓冲机制
带缓冲的channel适合于需连续传输大量数据的场景,定义一个带缓冲的channel,只需将容量传入make的第二个参数即可
   c := make(chan int, 1024)  //创建了一个大小为1024的整形chan,写入在缓冲区满前 不会阻塞
channel是可传递的

单向channel
单向channel只能用于发送或者接收数据。
声明
var ch1 chan int // ch1是一个正常的channel,不是单向的
var ch2 chan<- float64// ch2是单向channel,只用于写float64数据
var ch3 <-chan int // ch3是单向channel,只用于读取int数据
初始化
channel可以在单向channel和双向channel之间进行转换,channel本身就是GO的原生类型,因此可被传递,也可类型转换
ch4 := make(chan int)
ch5 := <-chan int(ch4) // ch5就是一个单向的读取channel
ch6 := chan<- int(ch4) // ch6 是一个单向的写入channel
关闭channel
直接用 close即可
close(ch)
判断channel是否已关闭,可以用多值返回读,如果第二个bool返回值是false则表示ch已经被关闭
x, ok := <-ch

select

用来监控一系列文件句柄发生的IO操作,一旦有其中一个句柄发生IO操作,则被返回
GO在语言级别支持select
代码结构大致如:
select {
<span style="white-space:pre">	</span>case <-chan1:
<span style="white-space:pre">	</span>// 如果chan1成功读到数据,则进行该case处理语句
<span style="white-space:pre">	</span>case chan2 <- 1:
<span style="white-space:pre">	</span>// 如果成功向chan2写入数据,则进行该case处理语句
<span style="white-space:pre">	</span>default:
<span style="white-space:pre">	</span>// 如果上面都没有成功,则进入default处理流程
}
其中每个case必须是一个文件句柄操作
结合for可实现循环检测
ch := make(chan int, 1)
for {
<span style="white-space:pre">	</span>select {
<span style="white-space:pre">		</span>case ch <- 0:
<span style="white-space:pre">		</span>case ch <- 1:
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>i := <-ch
<span style="white-space:pre">	</span>fmt.Println("Value received:", i)
}































有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:wolgame

查看原文:go基本语法学习笔记之并发编程

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1253 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传