空白每行不能超出99个字符。缩进只用空格,不用TAB。行和文件末尾不要有空白。空格二元运算符左右加空格,包括属性里的等号:#[deprecated = "Use `bar` instead."]fn foo(a: usize, b: usize) -> usize { a + b}在分号和逗号后面加空格:fn foo(a: Bar);MyStruct { foo: 3, bar: 4 }foo(bar, baz);
单元测试是用来校验程序的正确性的,然而,程序能正常运行后,往往还需要测试程序(一部分)的执行速度,这时,f就需要用到性能测试。通常来讲,所谓性能测试,指的是测量程序运行的速度,即运行一次要多少时间(通常是执行多次求平均值)。Rust 竟然连这个特性都集成在语言基础特性中,真的是一门很重视工程性的语言。下面直接说明如何使用。
程序测试是一种找到缺陷的有效方式,但是它对证明没有缺陷却无能为力。Edsger W. Dijkstra, "The Humble Programmer" (1972)作为软件工程质量保障体系的重要一环,测试是应该引起我们充分注意并重视的事情。前面说过,Rust 语言的设计集成了最近十多年中总结出来的大量最佳工程实践,而对测试的原生集成也正体现了这一点。下面来看 Rust 是怎么设计测试特性的。
本章讲解 Rust 中内建的测试与评测相关知识。
我们在使用toml描述文件对项目进行配置时,经常会遇到项目版本声明及管理的问题,比如:[package]name = "libevent_sys"version = "0.1.0"[dependencies]libc = "0.2"这里package段落中的version字段的值,以及dependencies段落中的libc字段的值,这些值的写法,都涉及到语义化版本控制的问题。语义化版本控制是用一组简单的规则及条件来约束版本号的配置和增长。
本章将介绍Rust编译器的参数。Rust编译器程序的名字是rustc,使用它的方法很简单:$ rustc [OPTIONS] INPUT其中,[OPTIONS]表示编译参数,而INPUT则表示输入文件。而编译参数有以下可选:-h, --help - 输出帮助信息到标准输出;--cfg SPEC - 传入自定义的条件编译参数,使用方法如fn main() { if cfg!(hello) { println!("world!");
属性(Attribute)是一种通用的用于表达元数据的特性,借鉴ECMA-334(C#)的语法来实现ECMA-335中描述的Attributes。属性只能应用于Item(元素、项),例如 use 声明、模块、函数等。元素在Rust中,Item是Crate(库)的一个组成部分。
本章将介绍Rust语言中的属性(Attribute)和编译器参数(Compiler Options)。
Rust可以让我们对某些运算符进行重载,这其中大部分的重载都是对std::ops下的trait进行重载而实现的。重载加法我们现在来实现一个只支持加法的阉割版复数:use std::ops::Add;#[derive(Debug)]struct Complex { a: f64, b: f64,}impl Add for Complex { type Output = Complex; fn add(self, other: Complex) ->
上一章讲述了如何从rust中调用c库,这一章我们讲如何把rust编译成库让别的语言通过cffi调用。调用约定和mangle正如上一章讲述的,为了能让rust的函数通过ffi被调用,需要加上extern "C"对函数进行修饰。但由于rust支持重载,所以函数名会被编译器进行混淆,就像c++一样。因此当你的函数被编译完毕后,函数名会带上一串表明函数签名的字符串。
下文提到的ffi皆指cffi。Rust作为一门系统级语言,自带对ffi调用的支持。Getting Start引入libc库由于cffi的数据类型与rust不完全相同,我们需要引入libc库来表达对应ffi函数中的类型。在Cargo.toml中添加以下行:[dependencies]libc = "0.2.9"在你的rs文件中引入库:extern crate libc在以前libc库是和rust一起发布的,后来libc被移入了crates.io通过cargo安装。
FFI(Foreign Function Interface)是用来与其它语言交互的接口,在有些语言里面称为语言绑定(language bindings),Java 里面一般称为 JNI(Java Native Interface) 或 JNA(Java Native Access)。
Rust通过限制智能指针的行为保障了编译时安全,不过仍需要对指针做一些额外的操作。*const T和*mut T在Rust中被称为“裸指针”。它允许别名,允许用来写共享所有权的类型,甚至是内存安全的共享内存类型如:Rc<T>和Arc<T>
Rust的内存安全依赖于强大的类型系统和编译时检测,不过它并不能适应所有的场景。首先,所有的编程语言都需要跟外部的“不安全”接口打交道,调用外部库等,在“安全”的Rust下是无法实现的; 其次,“安全”的Rust无法高效表示复杂的数据结构,特别是数据结构内部有各种指针互相引用的时候;再次,事实上还存在着一些操作,这些操作是安全的,但不能通过编译器的验证。
本章开始讲解 Rust 中的 Unsafe 部分。
理论上并行和语言并没有什么关系,所以在理论上的并行方式,都可以尝试用Rust来实现。本小节不会详细全面地介绍具体的并行理论知识,只介绍用Rust如何来实现相关的并行模式。Rust的一大特点是,可以保证“线程安全”。而且,没有性能损失。
同步指的是线程之间的协作配合,以共同完成某个任务。在整个过程中,需要注意两个关键点:一是共享资源的访问, 二是访问资源的顺序。通过前面的介绍,我们已经知道了如何让多个线程访问共享资源,但并没介绍如何控制访问顺序,才不会出现错误。
在消息传递之外,还存在一种广为人知的并发模型,那就是共享内存。其实如果不能共享内存,消息传递也是不能在不同的线程间传递消息,也谈不上在不同的线程间等待和通知了。共享内存是这一切得以发生的基础。如果查看源码,你会发现消息传递的内部实现就是借用了共享内存机制。
稍加考虑,上一节的练习题其实是不完整的,它只是评分系统中的一环,一个评分系统是需要先把信息从数据库或文件中读取出来,然后才是评分,最后还需要把评分结果再保存到数据库或文件中去。如果一步一步串行地做这三个步骤,是完全没有问题的。那么我们是否可以用三个线程来分别做这三个步骤呢?
并发是什么?引用Rob Pike的经典描述:并发是同一时间应对多件事情的能力其实在我们身边就有很多并发的事情,比如一边上课,一边发短信;一边给小孩喂奶,一边看电视,只要你细心留意,就会发现许多类似的事。相应地,在软件的世界里,我们也会发现这样的事,比如一边写博客,一边听音乐;一边看网页,一边下载软件等等。显而易见这样会节约不少时间,干更多的事。
关注时代Java