Attributes offer the ability to add structured, machine-readable metadata information on declarations in code.

Structures, interfaces, enums, methods, functions, fields, constants, and modules can be the target of an attribute. The metadata defined by attributes can then be inspected at compile-time using the Reflection APIs. Attributes could therefore be thought of as a configuration language embedded directly into code.

Attributes in V are declared inside square brackets [] before the declaration.

[inline] fn foo() {}

If multiple attributes need to be declared, they must be separated by ; (semicolon):

[inline; unsafe] fn foo() {}

You can also declare attributes on multiple lines:

[inline] [unsafe] fn foo() {}

Attributes can have a value that is specified after the attribute name:

[deprecated: 'use new_function() instead'] fn foo() {}

Field attributes of structures or interfaces are specified after the field declaration:

struct Foo { name string [sql: 'Name'] }

The special syntax of the if attribute allows you to specify a condition under which the definition will be compiled:

[if debug] fn log() {}

For custom options:

[if my_trace ?] fn log() {}

You also can declare string attribute:

['/run'] fn run() {}