结构体
结构体定义
结构体命名必须是大写字母开头,如果是小写字母开头会编译报错。
struct Point {
x int
y int
}
fn main() {
p := Point{
x: 10
y: 20
}
println(p.x) // 结构体字段通过点号来访问
}结构体被分配到内存的栈中,引用类型。
使用&来取结构体的地址
p2 := &Point{10, 10}
println(p2.x)空结构体:
sizeof( )可以返回结构体占用内存字节大小。
字段
结构体字段默认也是不可变,使用mut为可变。
结构体字段的可变性和访问控制,参考访问控制章节。
如果结构体字段名需要是关键字,可以通过使用@作为前缀也可以编译通过。
这一点在跟C库集成时比较常用,一些C库的struct的字段有些刚好是V的关键字,可以使用@前缀,编译成C代码时@前缀会被去掉,刚好就是C的struct中的字段名。
结构体字段支持默认值:
结构体字段的类型可以是任何类型,甚至可以是函数类型:
结构体字段初始化时必录:
结构体变量可以基于另一个变量创建,同时合并新的字段值:
当函数的参数是结构体变量时,这个语法可以简化结构体变量的创建,这个语法在ui模块比较常用到,用来简化函数参数。
选项字段:
跟函数的返回值类似:字段类型前加问号?表示:字段可能返回正常的类型或返回空值,即 T | none,如果字段返回none,则会触发空值错误,进入or代码块。
访问控制
结构体默认是模块级别的,使用pub关键字定义公共级别。
组合
跟go一样,V的结构体没有继承,但是有组合,可以用组合来实现继承一样的效果,多个组合也是可以的。
匿名结构体
在定义结构体字段时,除了使用已经定义好的结构体作为类型,也可以使用匿名结构体。
结构体初始化
常用的结构体初始化有2种:
字面量初始化
构造函数初始化
带组合的结构体初始化
空值初始化引用类型字段
引用类型的结构体字段必须进行初始化:
泛型结构体
参考泛型章节。
结构体注解
结构体像函数那样支持注解,可以针对结构体,结构体字段,结构体方法进行注解。
@[typedef]
typedef注解目前主要用在集成C代码库,详细参考集成C代码章节。
@[heap]
heap表示该结构体只能在内存的堆上创建,只能以引用的形式被使用。
可以参考标准库sync中WaitGroup的实际使用:
vlib/sync/waitgroup.v
@[noinit]
使用@[noinit]标志后,结构体只能在本模块内使用Foo{ }来创建变量,在其他模块中禁止直接使用字面量Foo{ }来初始化变量,只能使用模块提供的构造函数来创建。
@[params]
使用结构体的参数注解,可以用来实现函数参数的默认值和命名参数。
@[table]
在内置的orm中使用,用于定义模型结构体对应的数据库表名
@[minify]
对结构体的内存布局进行优化,占用内存空间更小,会使用C语言的位字段,把布尔类型从占用1个字节精简为1个位,把枚举占用的内存字节数也降低。这个参数已被使用到V的编译器代码中,编译器的内存占用大约降低了8M。
@[packed]
不让编译器进行结构体内存对齐。
关于内存对齐可参考:https://www.zhihu.com/question/27862634
@[autostr: allowrecurse]
这个注解告诉编译器,允许解析嵌套自身的结构体,而不用担心循环引用,确保结构体的print相关函数正确输出。
输出:
如果没有这个这个注解,则会输出:
结构体字段注解
@[required]
要求结构体字段在初始化的时候必须赋值
用于内置json解析支持,详细参考json章节。
结构体字段必须初始化赋值注解。
@[deprecated]
结构体字段作废
可以将结构体的某个字段标注为作废字段,并且可以加上作废开始日期。
只有在其他模块中直接访问作废字段,才会出发过期作废的提示或警告。
abc.v
main.v
结构体方法注解
跟函数注解一样,也可以对结构体方法进行注解。
结构体反射
可以通过编译时反射,实现动态获取结构体的所有字段,所有方法,并且可以动态设置字段值。
具体可以参考:编译时反射章节。
结构体字段内存位置偏移
__offsetof函数实现C的offsetof函数那样,返回结构体中某个字段的内存偏移量。
最后更新于
这有帮助吗?