模块
V语言是模块化的语言,程序由模块组成。
函数,结构体,常量,枚举等一级元素都要在模块中定义。
定义模块
定义模块的关键字是module。
模块对应的就是文件系统的目录,要定义一个新模块,先创建一个模块目录,然后在目录中创建.v的源文件,一个模块目录中可以创建多个源文件。
模块目录名一定要跟源文件中第一行定义的模块名一致。
比如模块目录名为mymodule,那么目录中的源文件第一行的模块定义也要一样,否则无法编译通过。
主模块
主模块及其依赖模块编译后,会生成对应平台的单一可执行文件。默认生成的可执行文件名为主函数所在的文件名。如果要指定生成的可执行文件名,可使用-o参数:
库模块
库模块编译后会生成对应的库文件,文件扩展名为.o。
模块目录
除了可以将V源代码文件统一放在模块根目录中,也可以将所有的源代码文件统一放在模块的src子目录中,编译器也会自动查找并编译src子目录中的所有源代码文件,这样可以让模块根目录更简洁。
需要注意的是,源代码文件要么全部放在模块根目录中,要么全部放在src目录中。不能一部分在模块根目录,一部分在src目录,如果出现这样的情况,编译器只会编译模块根目录中的源文件,忽略src目录的源文件,导致编译器报错,找不到src目录中定义的元素。
导入模块
导入模块的关键字是import。
导入模块取别名
上面的2种导入模块方式,使用时都需要带上模块名作为前缀。
短名称导入
模块内公共的函数,结构体,常量可以直接导入,使用时不需要模块名前缀。
匿名导入
支持模块匿名导入,匿名导入仅会执行模块的init初始化函数。
循环依赖检查
当前模块导入其他模块后,就形成了模块依赖,模块间不允许循环依赖,编译器在编译时会进行检查。
模块使用检查
如果导入的模块没有被使用,开发模式(v run xxx.v)下,编译器只是警告,仍然继续编译,方便开发调试,而不用去临时注释掉。
生产编译模式(v -prod xxx.v)下,编译器会报错,停止编译。
使用模块内容
导入模块后,就可以使用模块中的内容,目前模块的一级元素有7个:
const 常量
enum 枚举
fn 函数/方法
struct 结构体
union 联合体
interface 接口
type 类型别名
只有公共(pub)的一级元素才可以被其他模块访问,非公共的元素只能在模块内部使用。
mymodule.v
main.v
模块初始化/清除函数
如果在模块中定义了init函数,当模块被导入时,init函数会被自动调用;如果定义了cleanup函数,当程序退出时,cleanup函数会被自动调用。
同一个模块内只能定义一个init函数或cleanup函数,如果定义了多个,编译会不通过。
mymodule.v
main.v
执行结果是
模块作废
如果模块被作废,可以通过使用deprecated或deprecated_after注解来进行标注,编译时会提示模块使用者作废信息。
模块搜索路径
当使用import导入模块时,编译器会按以下顺序搜索模块: (可以在编译时使用 -v 参数查看编译时模块的搜索路径)
v.mod文件所在目录(当前编译中的源文件所在目录及其父目录(最大搜索深度255层)查找v.mod文件)。
入口源文件所在目录。
入口源文件所在目录中的modules子目录。
标准模块目录,即v/vlib。
第三方模块目录VMODULES。如果设置了VMODULES环境变量,则搜索环境变量指向的目录;如果没有设置VMODULES环境变量,则搜索默认目录~/.vmodules。
当前工作目录。
当前编译中的源文件目录路径中的modules目录(如果存在的话)。
当前编译中的源文件的所有父目录。
最后更新于