并发

协程

使用go关键字后面跟着函数调用, 可以将这个函数的执行过程放在另一个协程(新手可以粗暴理解为新的进程) go func(){ sleep(3); // 等待3秒 print("Inside!"); }() print("Outside")

多协程并发任务

如果你有一系列的任务, 并且任务的参数都放在了一个数组内, 那么数组的asyncMap方法可以帮你并发地执行这些任务 var start = now(); var res = [1, 2, 3, 4].asyncMap(e => { sleep(3); // 假如计算e*e是一个需要耗时3秒的行为 return e * e; }, 4); // 4个并发 print(fmt.Sprintf("Cost time %v, Result: %v", now().Sub(start), res)); 将上例的.asyncMap替换成.map即可测试无并发的情况

并发锁

并发map

可参考map, 如 // 并发安全 m = new(sync.Map)

代码块

通过以下方法可以保证并发场景下全局仅有count个协程执行代码内容, count缺省为1 synchronized(lock, [count]) { // 代码内容 } 其中lock参数可以为string类型(推荐)或其它可序列化的对象

通道

声明

可以通过以下语句声明一个通道 c = new('chan') // 声明一个不限定类型的通道 c = new('chan', 0) // 声明一个指定类型的通道, 第二个参数用于获取参数 c = new('chan', 0, 1) // 第三个参数用于指定缓冲区的大小 c = new('chan', 0, 1, 'w') // 第四个参数指定了通道是否只读、只写

读取数据

从通道读取数据: <- c // 阻塞到通道获取到值 rec = (<- c) // 读取并赋值 rec <- c // 从读取值声明一个当前作用域的变量 chanrecv(c) // 阻塞读取 chanrecv(c, true) // 不阻塞(尝试)读取 chanrecv(c, c1, c2...) // 从多个通道读取最先有值传递的 chanrecv(c, c1, 3...) // 传入int或float时, 表示设置读取超时时间 值得一提的是, 以上所有<-都可以换成->, 然后将两边调换即可

写入数据

将数据写入通道: c <- "hahaha" // 将一个字符串写入通道 "heiheihei" -> c // 同样的效果 chansend(c, 123) // 使用方法写入, 尤其在chan chan xxx类型时必须使用该方法

示例

c = new('chan') go func(){ var s = now() print("Start listen from chan") rec <- c printf('Chan get %v after %v', rec, now().Sub(s)) }() print("Ready to send") sleep(3) "zwr" -> c print("Send over") PS: 当使用<-->时, 为了区分是读取还是写入操作, 要求双方不能同时为chan类型. 如果双方都是chan类型时[例如 new('chan', new('chan'))声明的用于传输通道的通道] 需要调用chanrecvchansend方法以显式指定操作