struct Point {
x int
y int
}
p := &Point{10, 10}
// References have the same syntax for accessing fields
println(p.x)
The type of p
is &Point
. It’s a to Point
. References are similar to Go pointers and C++ references.
Embedded structs
V doesn’t allow subclassing, but it supports embedded structs:
struct Widget {
mut:
x int
y int
}
struct Button {
Widget
title string
}
title: 'Click me'
}
button.x = 3
Without embedding we’d have to name the Widget
field and do:
button.widget.x = 3
All struct fields are zeroed by default during the creation of the struct. Array and map fields are allocated.
It’s also possible to define custom default values.
Required fields
struct Foo {
n int [required]
This example will not compile, since the field n
isn’t explicitly initialized:
_ = Foo{}
struct Point {
x int
y int
}
mut p := Point{
x: 10
y: 20
}
// you can omit the struct name when it's already known
p = {
x: 30
y: 4
}
assert p.y == 4
Omitting the struct name also works for returning a struct literal or passing one as a function argument.
Trailing struct literal arguments
V doesn’t have default function arguments or named arguments, for that trailing struct literal syntax can be used instead:
As you can see, both the struct name and braces can be omitted, instead of:
new_button(ButtonConfig{text:'Click me', width:100})
This only works for functions that take a struct for the last argument.
Access modifiers
struct Foo {
a int // private immutable (default)
mut:
c int // (you can list multiple fields with the same access modifier)
pub:
d int // public immutable (readonly)
pub mut:
e int // public, but mutable only in parent module
f int // public and mutable both inside and outside parent module
} // (not recommended to use, that's why the 'global' keyword
// starts with __)
For example, here’s the string
type defined in the builtin
module:
struct string {
str byteptr
pub:
len int
}
It’s easy to see from this definition that string
is an immutable type. The byte pointer with the string data is not accessible outside builtin
at all. The len
field is public, but immutable:
This means that defining public readonly fields is very easy in V, no need in getters/setters or properties.
struct User {
age int
}
fn (u User) can_register() bool {
return u.age > 16
}
user := User{age: 10}
println(user.can_register()) // "false"
user2 := User{age: 20}
println(user2.can_register()) // "true"
V doesn’t have classes, but you can define methods on types. A method is a function with a special receiver argument. The receiver appears in its own argument list between the fn
keyword and the method name.
In this example, the can_register
method has a receiver of type User
named u
. The convention is not to use receiver names like or this
, but a short, preferably one letter long, name.