V语言教程 - 高级主题

V语言是一个简单、快速、安全的编译型语言,比较适合于开发可维护的软件。

Google讨论组:


调用C函数

// https://vlang-zh.cn

#flag -lsqlite3

#include "sqlite3.h"

struct C.sqlite3 
struct C.sqlite3_stmt 

fn C.sqlite3_column_int(C.sqlite_stmt, int) int 

fn main() {
	path := 'sqlite3_users.db' 
	db := &C.sqlite3{} 
	C.sqlite3_open(path.cstr(), &db)

	query := 'select count(*) from users' 
	stmt := &C.sqlite3_stmt{} 
	C.sqlite3_prepare_v2(db, query.cstr(), - 1, &stmt, 0)
	C.sqlite3_step(stmt) 
	nr_users := C.sqlite3_column_int(res, 0)
	C.sqlite3_finalize(res)
	println(nr_users) 
}

编译时if

$if windows {
	println('Windows')  
}  
$if linux {
	println('Linux') 
} 
$if mac {
	println('macOS') 
} 

编译时if以美元符号$开头。目前只能用于检测OS类型。

编译时泛型(生成代码)

V语言虽然内置了JSON值,但是真正厉害的是用户可以自定义任何类型的序列化:

// TODO: planned in June
fn decode<T>(data string) T {
    mut result := T{}
    for field in T.fields {
        if field.typ == 'string' {
            result.$field = get_string(data, field.name)
        } else if field.typ == 'int' {
            result.$field = get_int(data, field.name)
        }
    }
    return result
}

// generates to:
fn decode_User(data string) User {
    mut result := User{}
    result.name = get_string(data, 'name')
    result.age = get_int(data, 'age')
    return result
}

有限的运算符重载

struct Vec {
	x int
	y int
}

fn (a Vec) str() string { 
	return '{$a.x, $a.y}' 
}

fn (a Vec) + (b Vec) Vec {
	return Vec {
		a.x + b.x, 
		a.y + b.y 
	}
}

fn (a Vec) - (b Vec) Vec {
	return Vec {
		a.x - b.x, 
		a.y - b.y
	}
}

fn main() { 
	a := Vec{2, 3}
	b := Vec{4, 5}
	println(a + b) // ==> "{6, 8}"  
	println(a - b) // ==> "{-2, -2}"  
}

运算符重载虽然和V语言简单的哲学有点冲突。但是科学计算和徒刑程序也是V语言瞄准的市场,运算符重载可以简化这类程序编写和可读性:

例如a + b + c * d的可读性显然秒杀a.add(b).add(c.mul(d))

为了提高安全性和可维护性,操作员重载有以下限制:

C/C++转码到V

TODO:C到V的转换已经完成。但是C++到V的转换将在明年提供。

V转换工具可以将C/C++代码转换为具有可读性的V代码。我们看下面的小例子:

#include <vector>
#include <string>
#include <iostream>

int main() {
    std::vector<std::string> s;
    s.push_back("V is ");
    s.push_back("awesome");
    std::cout << s.size() << std::endl;
    return 0;
}

运行v translate test.cpp命令将生成test.v文件:

fn main {
	mut s := []
	s << 'V is '
	s << 'awesome'
	println(s.len) 
} 

马上会推出一个在线的C/C++到V的转换服务。

什么时候需要将C转换为V代码,什么时候需要从V直接调用C函数?

如果C代码已经经过良好的测试,代码风格也很规范,那么从V直接调用C函数是推荐的。

不过将代码翻译为V代码有以下好处:

代码热加载

TODO

交叉编译

交叉编译只需要加一个os命令行参数:

v -os windows .

v -os linux .

(其它平台到macOS,不支持交叉编译。)

如果没有C代码依赖,这就是全部的工作。甚至使用ui或gg模块的图形应用也可以正常交叉编译。

V中跨平台的脚本

(六月底到来)

V语言可以提到Bash来编写部署和构建的脚本程序。

使用V写脚本的好处是捡东西,并且容易检测操作系统的类型。V语言脚本可以在类Unix系统和Windows上无缝运行。

V脚本程序以#v开头。它将使os模块中的函数全局化(因此os.ls()调用将简化为ls()调用)。

#v 

rm('build/*') 
// Same as:  
for file in ls('build/') {
	rm(file) 
}

mv('*.v', 'build/') 
// Same as:  
for file in ls('.') {
	if file.ends_with('.v') { 
		mv(file, 'build/') 
	} 
} 

然后像普通V程序一样编译,就可以得到对应平台可执行的程序:v deploy.v && ./deploy

或者是直接运行:v run deploy.v


关注光谷码农公众号,了解V语言更多资讯: