结构体

基本用法

struct Point {
    x int
    y int
}

mut p := Point{
    x: 10
    y: 20
}
println(p.x) // 通过点号访问字段
// 简化字面量语法
p = Point{10, 20}
assert p.x == 10

结构体字段可使用保留关键字:

struct Employee {
    type string
    name string
}

employee := Employee{
    type: 'FTE'
    name: 'John Doe'
}
println(employee.type)

堆结构体

结构体默认分配在栈上。使用 & 前缀可在堆上分配并获取引用:

p := &Point{10, 10}
println(p.x) // 引用语法相同

p 的类型是 &Point(指向 Point 的引用)。引用行为类似 Go 指针和 C++ 引用。

可变性规则:

struct Foo {
mut:
    x int
}

// 值拷贝可修改
mut a := Foo{1}
a.x = 2  // 允许

// 不可变实例的引用不可修改
fb := Foo{1}
mut b := &fb  // 错误:`fb` 不可变

// 可变实例的引用可修改
mut fc := Foo{1}
mut c := &fc
c.x = 2      // 修改成功
println(fc)  // 输出:Foo{x:2}

默认字段值

struct Foo {
    n   int      // 默认 0
    s   string   // 默认 ''
    a   []int    // 默认 []
    pos int = -1 // 自定义默认值
}

所有字段在创建时初始化为零值。可自定义默认值。

必填字段

使用 @[required] 标记字段为必须初始化:

struct Foo {
    n int @[required]
}
// 缺少初始化会编译失败
_ = Foo{} // 错误:缺少字段 n

简化字面量语法

// 自动推断类型
points := [Point{10, 20}, Point{20, 30}] 
// 函数参数可省略结构体名
fn new_point(p Point) {...}
new_point(x:10, y:20) 

结构体更新语法

struct User {
    name          string
    is_registered bool
}

fn register(u User) User {
    return User{...u, is_registered:true} // 保留原字段
}

mut user := User{name:'abc'}
user = register(user)
println(user) // {name:'abc', is_registered:true}

尾随结构体参数

替代默认参数/命名参数:

@[params] // 允许完全省略参数
struct ButtonConfig {
    text   string
    width  int = 70 // 默认值
}

fn new_button(c ButtonConfig) &Button {...}

button := new_button(text:'Click', width:100) // 省略 height

需用 @[params] 标记结构体,否则至少需指定一个字段。

访问修饰符

共有五种访问级别:

struct Foo {
        a int  // 私有不可变 (默认)
mut:    b int  // 私有可变
        c int  // 同组可多字段
pub:    d int  // 公共只读
pub mut:e int  // 仅父模块可修改
__global:f int // 全局可修改(不推荐)
}

匿名结构体

struct Book {
    author struct { // 匿名内嵌
        name string
        age  int
    }
}

book := Book{author: struct {name:'Samantha', age:24}}
assert book.author.name == 'Samantha'

静态类型方法

struct User {}

fn User.new() User { // 类型名.方法名
    return User{}
}

user := User.new() // 替代工厂函数

非构造函数,V 无类或构造函数概念。

[noinit]结构体

@[noinit] 禁止模块外初始化:

module sample
@[noinit]
pub struct Info { data string }

// 通过工厂函数创建
pub fn new_info(data string) !Info {...}

外部调用:

import sample
info := sample.new_info('data')! // 直接初始化会报错

方法

struct User { age int }

// 方法定义
fn (u User) can_register() bool {
    return u.age > 16
}

println(User{age:10}.can_register()) // false

方法需与接收者类型同模块,接收者命名建议简短。

嵌入结构体

struct Size {
mut: width int, height int
}

fn (s Size) area() int { return s.width * s.height }

struct Button {
    Size // 嵌入
    title string
}

// 直接访问嵌入字段/方法
mut button := Button{title:'Click', height:2}
button.width = 3
assert button.area() == 6

// 显式访问嵌入结构体
assert button.Size.area() == 6

初始化方式:

button = Button{
    Size: Size{width:3, height:2}
}
// 或单独赋值
button.Size = Size{width:4, height:5}

嵌入为混入(mixins)而非继承:

  • 不能类型转换
  • 字段名冲突时需显式指定(如 button.Size.area()