Best Practices, Idioms and Limitations

45.1 Idiomatic V

✅ Keep code simple. V favors one obvious way.

✅ Immutable by default. Use mut only where necessary.

✅ Handle every !T / ?T with or {}, propagation (!/?), or if guards. Don't panic in library code.

✅ Use sum types and exhaustive match for variants. Use interfaces for behavior.

✅ Use @[params] structs for many or optional parameters.

✅ Use pub deliberately. Keep module APIs small.

✅ Use snake_case names, tabs, and v fmt always.

✅ Use defer for cleanup. Use shared + lock or channels for concurrency.

✅ Write tests next to the code (_test.v). Use v vet in CI.

❌ Don't use unsafe unless needed. Document why when you do.

❌ Don't enable globals without strong reason.

❌ Don't rely on experimental features (autofree, native backend) for production without testing.

❌ Don't ignore compiler warnings. They become errors in -prod.

45.2 Known Limitations and Caveats (Pre-1.0)

The language and stdlib are still evolving: attribute syntax changed ([x] → @[x]), generics changed (<T> → [T]), vweb was replaced by veb, and go vs spawn semantics changed.

Autofree isn't production-ready. The default is the Boehm GC.

Compiler bugs and less mature tooling compared with Go/Rust. Smaller ecosystem.

Some advertised goals (e.g., complete absence of UB, full memory safety without a GC) are still in progress.

Pin a V commit or release for production builds, and test after v up.

45.3 Security Practices

Use ORM or parameterized SQL. Validate and sanitize input in veb handlers. Use TLS (net.mbedtls/OpenSSL). Keep -prod builds with bounds checks on. Avoid -no-bounds-checking for network-facing code. Use crypto.rand for secrets (not rand).