在 Golang 游戏leaf系列(一) 概述与示例 (下文简称系列一)中,提到过Go模块用于创建能够被 Leaf 管理的 goroutine。Go模块是对golang中go提供一些额外功能。Go提供回调功能,LinearContext提供顺序调用功能。善用 goroutine 能够充分利用多核资源,Leaf 提供的 Go 机制解决了原生 goroutine 存在的一些问题:
创新互联公司-专业网站定制、快速模板网站建设、高性价比浉河网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式浉河网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖浉河地区。费用合理售后完善,10多年实体公司更值得信赖。
我们来看一个例子(可以在 LeafServer 的模块的 OnInit 方法中测试):
这里的 Go 方法接收 2 个函数作为参数,第一个函数会被放置在一个新创建的 goroutine 中执行,在其执行完成之后,第二个函数会在当前 goroutine 中被执行。由此,我们可以看到变量 res 同一时刻总是只被一个 goroutine 访问,这就避免了同步机制的使用。Go 的设计使得 CPU 得到充分利用,避免操作阻塞当前 goroutine,同时又无需为共享资源同步而忧心。
这里主动调用了 d.Cb(-d.ChanCb) ,把这个回调取出来了。实际上,在skeleton.Run里会自己取这个通道
看一下源码:
New方法,会生成指定缓冲长度的ChanCb。然后调用Go方法就是先执行第一个func,然后把第二个放到Cb里。现在手动造一个例子:
这里解释一下,d.Go根据源码来看,实际也是调用了一个协程。然后上面两次d.Go并不能保证先后顺序。目前的输出结果是1+2那个先执行了,把3写入d.ChanCb,然后把3读出来,继续读时,d.ChanCb里没有东西,阻塞了。然后1+1那个协程启动了,最后又读到了2。
现在把time.Sleep(time.Second)的注释解开,会是啥结果呢
这里执行到time.Sleep睡着了,上面两个d.Go仍然是不确定顺序的,但是会各自的function先执行掉,然后陆续把cb写入d.ChanCb。看这次输出,1+2先写进去的。所以最后执行d.Cb时,就把3先读出来了。然后d.ChanCb的长度为1,说明还有一个,就是输出2了。
另外,就是close时会判断g.pendingGo
这个例子的意思很明显,NewLinearContext这种方式,即使先调用的慢了半秒,它还是会先执行完。
这里先是用了一个list,加入的时候用mutexLinearGo锁了,都加到最后。然后新开协程去处理,读的时候从最前面开始读,也要用mutexLinearGo锁。执行的时候,也要上锁mutexExecution,确保f()执行完并且写入g.ChanCb回调,这个mutexExecution锁才会解除。现在可以改造一个带回调的例子:
结果说明,确实是2先被写入了d.ChanCb。
1、双击【模块引用表】。
2、在弹出的窗口中选择你的易语言模块文件.EC文件--并双击
3、右键点击加载的模块
4、选择查看【模块信息】,调用里面的子程序。
打开已安装好的易语言主程序,然后在“新建对话框”→“Windows窗口程序”→鼠标左键双击或者“确定”,进入易语言新工程界面。
进入易语言IDE之后,选择“支持库面板”→“程序”→“模块引用表”双击或者单击鼠标右键选择“添加模块引用”,弹出“加入易模块文件对话框”,选择欲加入的易语言模块然后打开即可。
此时,查看“模块引用表”中是否存在刚刚引用的模块,如果存在的话说明模块引入成功,否则,模块引用失败(具体失败原因,这里不做陈述)。
如果“模块引用表”中出现刚刚引用的模块名称,接下来我们要测试模块的正确性(实践是检验真理的唯一标准嘛)。笔者就调用模块中的一个子程序,以作验证。
根据验证结果来判断,此次模块的引用是正确的。
在编写代码或开发软件的过程中,引用模块是非常普遍的。
添加声音资源
.版本 2
.子程序 _按钮1_被单击
播放音乐 (#GO, 假)
自绘的皮肤可以换背景 常用的皮肤不能换
本教程介绍 Go 中多模块工作区的基础知识。使用多模块工作区,您可以告诉 Go 命令您正在同时在多个模块中编写代码,并轻松地在这些模块中构建和运行代码。
在本教程中,您将在共享的多模块工作区中创建两个模块,对这些模块进行更改,并在构建中查看这些更改的结果。
本教程需要 go1.18 或更高版本。使用go.dev/dl中的链接确保您已在 Go 1.18 或更高版本中安装了 Go 。
首先,为您要编写的代码创建一个模块。
1、打开命令提示符并切换到您的主目录。
在 Linux 或 Mac 上:
在 Windows 上:
2、在命令提示符下,为您的代码创建一个名为工作区的目录。
3、初始化模块
我们的示例将创建一个hello依赖于 golang.org/x/example 模块的新模块。
创建你好模块:
使用 . 添加对 golang.org/x/example 模块的依赖项go get。
在 hello 目录下创建 hello.go,内容如下:
现在,运行 hello 程序:
在这一步中,我们将创建一个go.work文件来指定模块的工作区。
在workspace目录中,运行:
该go work init命令告诉为包含目录中模块的工作空间go创建一个文件 。go.work./hello
该go命令生成一个go.work如下所示的文件:
该go.work文件的语法与go.mod相同。
该go指令告诉 Go 应该使用哪个版本的 Go 来解释文件。它类似于文件中的go指令go.mod 。
该use指令告诉 Go在进行构建时hello目录中的模块应该是主模块。
所以在模块的任何子目录中workspace都会被激活。
2、运行工作区目录下的程序
在workspace目录中,运行:
Go 命令包括工作区中的所有模块作为主模块。这允许我们在模块中引用一个包,即使在模块之外。在模块或工作区之外运行go run命令会导致错误,因为该go命令不知道要使用哪些模块。
接下来,我们将golang.org/x/example模块的本地副本添加到工作区。然后,我们将向stringutil包中添加一个新函数,我们可以使用它来代替Reverse.
在这一步中,我们将下载包含该模块的 Git 存储库的副本golang.org/x/example,将其添加到工作区,然后向其中添加一个我们将从 hello 程序中使用的新函数。
1、克隆存储库
在工作区目录中,运行git命令来克隆存储库:
2、将模块添加到工作区
该go work use命令将一个新模块添加到 go.work 文件中。它现在看起来像这样:
该模块现在包括example.com/hello模块和 `golang.org/x/example 模块。
这将允许我们使用我们将在模块副本中编写的新代码,而不是使用命令stringutil下载的模块缓存中的模块版本。
3、添加新功能。
我们将向golang.org/x/example/stringutil包中添加一个新函数以将字符串大写。
将新文件夹添加到workspace/example/stringutil包含以下内容的目录:
4、修改hello程序以使用该功能。
修改workspace/hello/hello.go的内容以包含以下内容:
从工作区目录,运行
Go 命令在go.work文件指定的hello目录中查找命令行中指定的example.com/hello模块 ,同样使用go.work文件解析导入golang.org/x/example。
go.work可以用来代替添加replace 指令以跨多个模块工作。
由于这两个模块在同一个工作区中,因此很容易在一个模块中进行更改并在另一个模块中使用它。
现在,要正确发布这些模块,我们需要发布golang.org/x/example 模块,例如在v0.1.0. 这通常通过在模块的版本控制存储库上标记提交来完成。发布完成后,我们可以增加对 golang.org/x/example模块的要求hello/go.mod:
这样,该go命令可以正确解析工作区之外的模块。
易语言支持库模块,可以包括子程序的等价物,常量,自定义数据类型,你写一些你自己的例程的当量,定义的数据类型的常量,可以直接调用在程序的程序,但必须遵守与调用模块(例如:参数的参数的数据类型)的要求
易语言运行时会让你选择新的类型,其中之一是易语言模块,易语言模块,可以创建一个子程序,然后打上一个子程序的开回复选标记,写代码,然后编译该模块在编译另一个程序中引用后,你可以看到,有可能是一个参考的子程序,如果复选标记没打这么公开,将不会看到一个参考相应的模块子程序!