Gox语言中,基本完全继承了Go语言的并发机制和用于数据安全共享操作的通道类型chan。
关于chan类型的使用先看看Qlang中的使用说明,
chan 类型
ch1 = make(chan bool, 2) // 得到 buffer = 2 的 chan bool
ch2 = make(chan int) // 得到 buffer = 0 的 chan int
ch3 = make(chan map[string]int) // 得到 buffer = 0 的 chan map[string]int
和 Go 语言类似,chan 有如下内置的操作:
n = len(ch1) // 取得chan当前的元素个数
m = cap(ch1) // 取得chan的容量
ch1 <- true // 向chan发送一个值
v = <-ch1 // 从chan取出一个值
close(ch1) // 关闭chan,被关闭的chan是不能写,但是还可以读(直到已经写入的值全部被取完为止)
需要注意的是,在 chan 被关闭后,<-ch 取得 undefined 值。所以在 qlang 中应该这样:
v = <-ch1
if v != undefined { // 判断chan没有被关闭的逻辑
...
}
更详细一些的用法如下面的例子所示:
c = make(chan int)
go fn() {
for {
c <- 1
tk.SleepSeconds(1)
}
}()
go fn() {
for {
c <- 200
tk.SleepSeconds(1)
}
}()
go fn() {
for {
tmp = <-c
println(tmp)
tk.SleepMilliSeconds(500)
}
}()
for {
tk.SleepSeconds(5)
println("main thread")
}
这一段代码中,创建了3个Goroutine,可以理解为3个线程,其中前两个线程是每隔一秒钟向通道中写入一个数据,第三个线程则是每隔500毫秒从通道中读取一个数据并显示出来。另外,我们不要忘了主线程,主线程必须保持始终存在,否则子线程将会随着主线程的结束而全部退出。因此,我们主线程中进行了一个无限循环,每隔5秒钟输出一下信息。
另外注意,三个Goroutine都是用go加一个匿名函数的方式运行的,go的用法和Go语言中一样,也可以启动其他函数作为线程。
程序退出可以用Ctrl-C来进行,整个代码执行的结果类似下面(将无限重复下去直至按Ctrl-C终止):
λ gox chan.gox
1
200
1
200
1
200
1
200
1
200
main thread
1
200
1
200
* 注:由于0.988版本后,为了减少不必要的文件体积,Gox已经放弃了其他脚本引擎,仅支持Qlang引擎,因此下面的内容已经无效,仅留作对旧版本的参考。
而下面是Anko引擎的版本的用法,也是类似。
首先,非常方便地,任何函数都可以用go关键字启动为一个线程;然后通道可以用make(chan string)这样的方式来进行定义,Go语言中所谓的通道即是用于共享数据的并发安全的特有数据类型,具体的用法可以参考Go语言的官方文档。
更详细一些的用法如下面的例子所示:
tk = import("tk")
c = make(chan int64)
go func() {
for {
c <- 1
tk.SleepSeconds(1)
}
}()
go func() {
for {
c <- 200
tk.SleepSeconds(1)
}
}()
go func() {
for {
tmp = <-c
println(tmp)
tk.SleepMilliSeconds(500)
}
}()
for {
tk.SleepSeconds(5)
println("main thread")
}
这一段代码中,创建了3个Goroutine,可以理解为3个线程,其中前两个线程是每隔一秒钟向通道中写入一个数据,第三个线程则是每隔500毫秒从通道中读取一个数据并显示出来。另外,我们不要忘了主线程,主线程必须保持始终存在,否则子线程将会随着主线程的结束而全部退出。因此,我们主线程中进行了一个无限循环,每隔5秒钟输出一下信息。
程序退出可以用Ctrl-C来进行,整个代码执行的结果类似下面(将无限重复下去直至按Ctrl-C终止):
λ gox scripts\chan.gox
1
200
1
200
1
200
1
200
1
200
main thread
1
200
1
200
1
200