V语言10共享对象
共享对象
通过共享对象
在协程/线程
间交换数据.应按共享
创建并传递给协程
.构
底层包含一个锁
来锁住并发访问,rlock
针对只读
,而lock
针对读写
.
struct St {
mut:
x int //待共享数据
}
fn (shared b St) g() {//共享函数
lock b {
// 读改写 b.x
}
}
fn main() {
shared a := St{
x: 10
}
go a.g()
// ...
rlock a {
// 读a.x
}
}
共享变量必须为构,数组,映射
.
import json
struct Foo {
x int
}
struct User {
name string
age int
// 用跳过属性来跳过特定字段
foo Foo [skip]
//如果字段名与数格不同,可指定
last_name string [json: lastName]
}
data := "{ "name": "Frodo", "lastName": "Baggins", "age": 25 }"
user := json.decode(User, data) or {
eprintln("解码数格失败")
return
}
println(user.name)
println(user.last_name)
println(user.age)
// 也可解码数格数组
sfoos := "[{"x":123},{"x":456}]"
foos := json.decode([]Foo, sfoos) ?
println(foos[0].x)
println(foos[1].x)
V
内置支持数格
.json.decode
带两个参数:1为类型,2为串
.
V
生成加解密
数格代码,无运行时反射,性能更好.
测试
fn foo(mut v []int) {
v[0] = 1
}
mut v := [20]
foo(mut v)
assert v[0] < 4
assert
检查表达式为真
.失败则中止程序.应仅用来检测编程错误,错误时打印出比较两端值.
// 你好.v
module main
fn 你好() string {
return "你好啊"
}
fn main() {
println(你好())
}
//主
module main
// 你好_test.v
fn test_你好() {
assert 你好() == "你好啊"
}
v 你好_test.v
命令.v
在文件中执行所有测试函数.
序号 | 注意 |
---|---|
1 | 必须以_test.v 结尾, |
2 | 测试函数以test_ 开始, |
3 | 普通函数也可在测试中,但要手动调用, |
4 | 有两类测试:外部/内部 . |
5 | 内部测试必须声明模块名,可调用相同模块私函数 |
6 | 外部测试必须导入待测试 模块,仅能测试模块的外部/公开 函数. |
上面为内部测试
,内部测试可用来测试私有
函数
测试函数中特殊函数:testsuite_begin/end
在其他测试函数前后
运行.
import strconv
fn test_atoi() ? {
assert strconv.atoi("1") ? == 1
assert strconv.atoi("one") ? == 1 // test will fail
}
一个错误,就传播了.运行单个测试文件:v foo_test.v
.
测试整个模块,v test mymodule/v test .
.-stats
获取测试细节.你可在测试目录中放testdata
文件夹.特殊处理,都可这样.
V编译器路径
可由@VEXE
得到.
import os
fn test_subtest() {
res := os.execute("${@VEXE} other_test.v")
assert res.exit_code == 1
assert res.output.contains("other_test.v 不存在")
//这样就可编译测试文件了.
}
管理内存
V
第一时间用值类型/串缓冲
来避免不必要分配
.大多数代码>90%
用自动释放
引擎释放.编译期插入释放代码,剩余小部分用引用计数
释放.
开发者
不必改代码,就管用
了.没有厚重
的垃圾跟踪
或昂贵
的引用计数
.
你可利用V
的自动释放引擎,并对自己的类型定义释放
.
struct MyType {}
[unsafe]
fn (data &MyType) free() {
// ...
}//手动释放了.就像C++的析构函数
可用-manualfree
开关来手动管理内存,用于低级控制.函数上加[manualfree]
也可以.当前默认为-autofree
开关.不自动释放
,会泄露内存
.
import strings
fn draw_text(s string, x int, y int) {
// ...
}
fn draw_scene() {
// ...
name1 := "abc"
name2 := "def ghi"
draw_text("你好 $name1", 10, 10)
draw_text("你好 $name2", 100, 10)
draw_text(strings.repeat(`X`, 10000), 10, 50)
// ...
}
串
不转义draw_text
,所以退出函数,就清理了.
用-prealloc
标志,前2个根本不分配.是小串,所以给他们用预分配缓冲
.
struct User {
name string
}
fn test() []int {
number := 7 // 栈变量
user := User{} // 栈上构
numbers := [1, 2, 3] //堆上分配数组,退出函数时释放
println(number)
println(user)
println(numbers)
numbers2 := [4, 5, 6] //返回,因而不释放
return numbers2
}
ORM
α状态
,支持SQLite, MySQL和Postgres
,将支持MS SQL和Oracle
序号 | 好处 |
---|---|
1 | 统一语法 |
2 | 统一查询 |
3 | 安全 |
4 | 编译时检查 |
5 | 可读性/简单性 |
import sqlite
struct Customer {
//目前构名必须与表名相同
id int [primary; sql: serial] //`id`必须为第1字段
name string [nonull]
nr_orders int
country string [nonull]
}
db := sqlite.connect("customers.db") ?
// 可创建表
// CREATE TABLE IF NOT EXISTS `Customer` (`id` INTEGER PRIMARY KEY, `name` TEXT NOT NULL, `nr_orders` INTEGER, `country` TEXT NOT NULL)
sql db {
create table Customer
}
// select count(*) from Customer
nr_customers := sql db {
select count from Customer
}
println("顾客数: $nr_customers")
// 用V语法来构建查询
uk_customers := sql db {
select from Customer where country == "uk" && nr_orders > 0
}
println(uk_customers.len)
for customer in uk_customers {
println("$customer.id - $customer.name")
}
// 添加`limit 1`告诉V,只1个对象
customer := sql db {
select from Customer where id == 1 limit 1
}
println("$customer.id - $customer.name")
// 插入新顾客
new_customer := Customer{
name: "张三"
nr_orders: 10
}
sql db {
insert new_customer into Customer
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现