Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

命名

使用统一的命名风格

Rust 倾向于在“类型”级的结构中使用大驼峰(UpperCamelCase) 命名风格,在 “变量、值(实例)、函数名”等结构中使用蛇形(snake_case)命名风格。

下面是汇总信息:

Item规范
包(Crates)通常使用 snake_case
模块(Modules)snake_case
类型(Types)UpperCamelCase
特质(Traits)UpperCamelCase
枚举体(Enum variants)UpperCamelCase
函数(Functions)snake_case
方法(Methods)snake_case
通用构造函数(General constructors)new 或者 with_more_details
转换构造函数(Conversion constructors)from_some_other_type
宏(Macros)snake_case!
本地变量(Local variables)snake_case
静态变量(Statics)SCREAMING_SNAKE_CASE
常量(Constants)SCREAMING_SNAKE_CASE
类型参数(Type parameters)简明的 UpperCamelCase ,通常使用单个大写字母: T
生命周期(Lifetimes)简短的 lowercase,通常使用单个小写字母 'a, 'de, 'src,尽量保持语义
特性(Features)snake_case

说明 :

  1. UpperCamelCase情况下,由首字母缩写组成的缩略语和 复合词的缩写,算作单个词。比如,应该使用 Uuid 而非 UUID,使用 Usize 而不是 USize,或者是 Stdin 而不是 StdIn
  2. snake_case中,首字母缩写和缩略词是小写的 is_xid_start
  3. snake_case 或者 SCREAMING_SNAKE_CASE 情况下,每个词不应该由单个字母组成——除非这个字母是最后一个词。比如,使用 btree_map 而不使用 b_tree_map,使用 PI_2 而不使用 PI2

关于包命名:

  • 由于历史问题,包名有两种形式 snake_casekebab-case ,但实际在代码中需要引入包名的时候,Rust 只能识别 snake_case,也会自动将 kebab-case 识别为 kebab_case。所以建议使用snake_case
  • Crate 的名称通常不应该使用 -rs 或者 -rust 作为后缀或者前缀。但是有些情况下,比如是其他语言移植的同名 Rust 实现,则可以使用 -rs 后缀来表明这是 Rust 实现的版本。

Rust 命名规范在 RFC 0430 中有也描述。

Lint 检测

lint nameClippy 可检测Rustc 可检测Lint Group
Rustc: non_camel_case_typesnoyesStyle
Rustc: non_snake_casenoyesStyle

类型转换函数命名需要遵循所有权语义

进行特定类型转换的方法名应该包含以下前缀:

名称前缀内存代价所有权
as_无代价borrowed -> borrowed
to_代价昂贵borrowed -> borrowed
borrowed -> owned (非 Copy 类型)
owned -> owned (Copy 类型)
into_看情况owned -> owned (非 Copy 类型)

as_into_ 作为前缀的类型转换通常是 降低抽象层次 ,要么是查看背后的数据 ( as ) ,要么是分解 (deconstructe) 背后的数据 ( into ) 。 相对来说,以 to_ 作为前缀的类型转换处于同一个抽象层次,但是底层会做更多工作,比如多了内存拷贝等操作。

当一个类型用更高级别的语义 (higher-level semantics) 封装 (wraps) 一个内部类型时,应该使用 into_inner() 方法名来取出被封装类型的值。

同一个crate中标识符的命名规则应该使用统一的词序

具体选择什么样的词序并不重要,但务必要保证同一个 crate 内词序的一致性。 若提供与标准库中相似功能的东西时,也要与标准库名称的词性顺序一致.

拿错误类型来举个例子:

当crate中类型名称都按照 动词-宾语-error 这样的顺序来命名错误类型时,如果要增加新的错误类型,则也需要按同样的词序来增加。

struct AddrParseError {}// 不符合:与标准库错误类型词序 "`动-宾-Error`"  不一致,应该为 `ParseAddrError`
struct ParseAddrError{} // 符合: 与标准库错误类型一致

标识符命名应该符合阅读习惯

一些好的实践包括但不限于:

  • 使用正确的英文单词并符合英文语法,不要使用拼音
  • 仅使用常见或领域内通用的单词缩写
  • 布尔型变量或函数避免使用否定形式,双重否定不利于理解
  • 不要使用Unicode 标识符

作用域越大命名越精确,反之应简短

  • 对于全局函数、全局变量、宏、类型名、枚举命名,应当精确描述并全局唯一。
  • 对于函数局部变量,或者结构体、枚举中的成员变量,在其命名能够准确表达含义的前提下,应该尽量简短,避免冗余信息重复描述。
// 不符合:描述不精确
static GET_COUNT: i32 = 42;
// 不符合:信息冗余
enum WebEvent {
    PageLoadEvent,
    PageUnloadEvent,
    KeyPressEvent(char),
    PasteEvent(String),
    ClickEvent { x: i64, y: i64 },
}
// 不符合:信息冗余
type MaskSize = u16;
pub struct HeaderMap {
mask: MaskSize,
}
#![allow(unused)]
fn main() {
// 符合
static MAX_THREAD_COUNT: i32 = 42;
// 符合: 上下文信息已经知道它是 Event
enum WebEvent {
    PageLoad,
    PageUnload,
    KeyPress(char),
    Paste(String),
    Click { x: i64, y: i64 },
}
// 符合:在使用它的地方自然就知道是描述谁的大小
type Size = u16;
pub struct HeaderMap {
    mask: Size,
}
}

避免使用语言内置保留字、关键字、内置类型和trait等特殊名称

命名必须要避免使用语言内置的保留字、关键字、内置类型和trait等特殊名称

具体可以参考The Rust Reference-Keywords

避免在变量的命名中添加类型标识

因为Rust语言类型系统崇尚显式的哲学,所以不需要在变量命名中也添加关于类型的标识。

#![allow(unused)]
fn main() {
    let account_bytes: Vec<u8> = read_some_input();   // 不符合:account 的类型很清楚,没必要在命名中加 `_bytes`
    let account_str = String::from_utf8(account_bytes)?; // 不符合:account 的类型很清楚,没必要在命名中加 `_str`
    let account: Account = account_str.parse()?;   // 不符合:account 的类型很清楚,没必要在命名中加 `_str`
}

定义全局静态变量时需加前缀G_以便和常量有所区分

为了提升代码可读性和可维护性,有必要将常量的命名和全局静态变量加以区分。所以在定义全局静态变量时,需要以前缀G_命名。

// 不符合: 无法通过命名直接区分常量和静态变量
static EVENT: [i32;5]=[1,2,3,4,5];
const MAGIC_NUM: i32 = 65 ;

// 符合: 通过前缀区分常量和静态变量   
static G_EVENT: [i32;5]=[1,2,3,4,5];
const MAGIC_NUM: i32 = 65 ;