结构体

结构体定义

结构体命名必须是大写字母开头,如果是小写字母开头会编译报错。

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种:

  1. 字面量初始化

  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]

要求结构体字段在初始化的时候必须赋值

  1. 用于内置json解析支持,详细参考json章节

  2. 结构体字段必须初始化赋值注解。

@[deprecated]

结构体字段作废

可以将结构体的某个字段标注为作废字段,并且可以加上作废开始日期。

只有在其他模块中直接访问作废字段,才会出发过期作废的提示或警告。

abc.v

main.v

结构体方法注解

跟函数注解一样,也可以对结构体方法进行注解。

结构体反射

可以通过编译时反射,实现动态获取结构体的所有字段,所有方法,并且可以动态设置字段值。

具体可以参考:编译时反射章节

结构体字段内存位置偏移

__offsetof函数实现C的offsetof函数那样,返回结构体中某个字段的内存偏移量。

最后更新于

这有帮助吗?