structFoo { a int b int=7//默认值7}fnmain() { foo := Foo{ a: 1 }println(foo.a) //输出1println(foo.b) //输出默认值7 foo2 := Foo{ a: 1 b: 2 }println(foo2.b) //输出2}
结构体字段的类型可以是任何类型,甚至可以是函数类型:
module mainstructAbc { f1int f2int f3fn (int,int) int//结构体字段类型为函数类型}fnadd(x int, y int) int {return x + y}fnmain() { a1 := Abc{ f1: 123 f3: fn (x int, y int) int {return x + y } } a2 := Abc{ f1: 123 f2: 789 f3: add }println(a1)println(a2)}
结构体字段初始化时必录:
structPoint { x int y int z int [required] //字段注解required表示必须初始化赋值}fnmain() { a := Point{// x: 1 //不会报错,x不是必须初始化赋值 y: 3 z: 5 } b := Point{ x: 2 y: 4// z: 6 //报错: field `Point.z` must be initialized }println(a)println(b)}
结构体变量可以基于另一个变量创建,同时合并新的字段值:
module mainstructCity { name string population int}structCountry { name string capital City}fnmain() { c := Country{ name: 'test' capital: City{ name: 'city' } } c2 := Country{ ...c // 在c的基础上创建c2变量 capital: City{ name: 'city2' population: 200 } }println(c2)}
module mainstructUser { name string age int}fnadd(u User) {println(u)}fnmain(){add(User{name:'jack',age:22}) //标准方式add(name:'tt',age:33) //简短的方式,省略类型和大括号,有命名参数调用的感觉}
选项字段:
跟函数的返回值类似:字段类型前加问号?表示:字段可能返回正常的类型或返回空值,即 T | none,如果字段返回none,则会触发空值错误,进入or代码块。
module mainstructFoo {mut: x ?int=1//字段可以返回正常类型或者none y ?int=none//字段默认值为none,触发空值错误,进入or代码块}fnmain() {mut f := Foo{}println(f.x?) //输出1 f = Foo{ x: 2 y: none } a := f.x or { 123 }println(a) // 输出2 b := f.y or { 9999 } // f.y返回空值none,触发空值错误,进入or代码块println(b) // 输出9999mut sum := f.x?+1 sum = f.x or { 123 } +1println(sum) // 输出3}
访问控制
结构体默认是模块级别的,使用pub关键字定义公共级别。
pubstructPoint { //公共级别,可以被别的模块使用 x int y int}
组合
跟go一样,V的结构体没有继承,但是有组合,可以用组合来实现继承一样的效果,多个组合也是可以的。
module mainstructWidget {mut: x int y int}pub fnnew_widget(x int, y int) Widget {return Widget{ x: x y: y }}pub fn (mut w Widget) move(x_step int, y_step int) { w.x += x_step w.y += y_step}structWidget2 {mut: z int}pub fnnew_widget2(z int) Widget2 {return Widget2{ z: z }}pub fn (mut w Widget2) move_z(z_step int) { w.z += z_step}structButton { Widget //组合 Widget2//多个组合 title string}fnmain() {mut button := Button{ title: 'Click me' } button.x =3// Button的x字段来自Widget button.z =4// Button的z字段来自Widget2println('x:$button.x,y:$button.y,z:$button.z') button.move(3,4) // Button的move方法来自Widgetprintln('x:$button.x,y:$button.y,z:$button.z') button.move_z(5) // Button的move_z方法来自Widget2println('x:$button.x,y:$button.y,z:$button.z')}
匿名结构体
在定义结构体字段时,除了使用已经定义好的结构体作为类型,也可以使用匿名结构体。
module mainstructBook { x string author struct { //匿名结构体 name string age int } author2struct { //匿名结构体也可以是空结构体 } title string}fnmain() { book := Book{ author: struct {'sdf',23} // 初始化匿名结构体字段时,也需要使用struct关键字 author2: struct {} }println(book)println(book.author.age)}
module mainstructPoint { x int y int}structWindow {pub: p &Point =unsafe { nil } // 空值初始化引用类型字段,替代原来的voidptr(0)值}fnmain() { p :=&Point{1,3} w := Window { p:p }println(w)}
module mymodule@[noinit]pubstructResult {}//模块内的构造函数pub fnnew_result() Result {return Result{}}
module mainimport mymodulefnmain() {// 报错:it cannot be initialized with `mymodule.Result{}`// res := mymodule.Result{} res := mymodule.new_result() //调用模块提供的构造函数是可以的println(res)}
@[table: 'userlist'] //自定义表名structUser { id int [primary; sql: serial] age int name string [sql: 'username'] is_customer bool skipped_string string [skip]}
module mainstructFoo { a i64// 8字节 b int// 4字节}@[packed]structBar { a i64 b int}pub fnmain() {println(sizeof(Foo)) // 16,编译器会进行内存对齐println(sizeof(Bar)) // 12,不让编译器进行内存对齐}
structPoint { x int y int z int [required] //字段注解required表示必须初始化赋值}fnmain() { a := Point{// x: 1 //不会报错,x不是必须初始化赋值 y: 3 z: 5 } b := Point{ x: 2 y: 4// z: 6 //报错: field `Point.z` must be initialized }println(a)println(b)}
@[deprecated]
结构体字段作废
可以将结构体的某个字段标注为作废字段,并且可以加上作废开始日期。
只有在其他模块中直接访问作废字段,才会出发过期作废的提示或警告。
abc.v
module abcpubstructPoint {pubmut: x_new int x int [deprecated: 'use Point.x_new instead'; deprecated_after: '2999-03-01']}
module mainstructUser { name [50]u8 age int desc string}fnmain() { offset_name:=__offsetof(User,name) offset_age:=__offsetof(User,age) offset_desc:=__offsetof(User,desc)println(offset_name)println(offset_age)println(offset_desc)}