Rust 库开发全面指南
Rust 库开发全面指南
在 Rust 中开发库(lib)是创建可重用代码的核心方式。下面我将详细介绍如何创建、开发和发布 Rust 库。
创建库项目
cargo new --lib mylib
cd mylib
项目结构:
mylib/
├── Cargo.toml
└── src/└── lib.rs
核心开发流程
1. 定义公共接口 (src/lib.rs)
//! 这是一个数学计算库
//!
//! 提供各种数学计算功能/// 计算两个数的和
///
/// # 示例
/// ```
/// use mylib::add;
///
/// assert_eq!(add(2, 3), 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {a + b
}/// 计算阶乘
pub fn factorial(n: u64) -> u64 {(1..=n).product()
}/// 自定义错误类型
#[derive(Debug)]
pub enum MathError {DivisionByZero,NegativeNumber,
}/// 安全除法
pub fn safe_divide(a: f64, b: f64) -> Result<f64, MathError> {if b == 0.0 {Err(MathError::DivisionByZero)} else {Ok(a / b)}
}
2. 添加模块化结构
创建新文件 src/math.rs
:
/// 高级数学运算
pub mod advanced {/// 计算斐波那契数列pub fn fibonacci(n: u32) -> u64 {match n {0 => 0,1 => 1,_ => fibonacci(n - 1) + fibonacci(n - 2),}}
}
在 src/lib.rs
中引入:
pub mod math;
3. 添加单元测试
#[cfg(test)]
mod tests {use super::*;#[test]fn test_add() {assert_eq!(add(2, 2), 4);}#[test]fn test_factorial() {assert_eq!(factorial(5), 120);}#[test]fn test_safe_divide() {assert!(safe_divide(10.0, 0.0).is_err());assert_eq!(safe_divide(10.0, 2.0), Ok(5.0));}
}
4. 添加集成测试
创建 tests/integration_test.rs
:
use mylib::{add, math::advanced::fibonacci};#[test]
fn test_add_integration() {assert_eq!(add(10, 20), 30);
}#[test]
fn test_fibonacci() {assert_eq!(fibonacci(10), 55);
}
高级功能开发
1. 自定义类型
// src/geometry.rs
#[derive(Debug, PartialEq, Clone)]
pub struct Point {pub x: f64,pub y: f64,
}impl Point {pub fn new(x: f64, y: f64) -> Self {Point { x, y }}pub fn distance(&self, other: &Point) -> f64 {((self.x - other.x).powi(2) + (self.y - other.y).powi(2)).sqrt()}
}
2. 特征(Trait)系统
// src/shapes.rs
pub trait Area {fn area(&self) -> f64;
}pub struct Circle {pub radius: f64,
}impl Area for Circle {fn area(&self) -> f64 {std::f64::consts::PI * self.radius.powi(2)}
}
3. 宏开发
// src/macros.rs
#[macro_export]
macro_rules! vec2d {($($x:expr),*) => {{let mut temp_vec = Vec::new();$(temp_vec.push($x);)*temp_vec}};
}
配置 Cargo.toml
[package]
name = "mylib"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <your.email@example.com>"]
description = "A comprehensive math and geometry library"
license = "MIT OR Apache-2.0"
repository = "https://github.com/yourusername/mylib"
documentation = "https://docs.rs/mylib"# 更多元数据
[package.metadata.docs.rs]
all-features = true# 依赖管理
[dependencies]
serde = { version = "1.0", features = ["derive"], optional = true }
rand = "0.8"# 可选特性
[features]
default = ["serde"]
geometry = [] # 启用几何功能
advanced = ["geometry"] # 启用高级功能# 开发依赖
[dev-dependencies]
approx = "0.5" # 用于浮点数比较
文档系统
1. 编写文档注释
/// 计算两点之间的距离
///
/// # 示例
/// ```
/// use mylib::geometry::Point;
///
/// let p1 = Point::new(0.0, 0.0);
/// let p2 = Point::new(3.0, 4.0);
/// assert_eq!(p1.distance(&p2), 5.0);
/// ```
pub fn distance(&self, other: &Point) -> f64 {// ...
}
2. 生成文档
cargo doc --open
测试与基准测试
1. 单元测试
#[test]
fn test_point_distance() {let p1 = Point::new(0.0, 0.0);let p2 = Point::new(3.0, 4.0);assert_relative_eq!(p1.distance(&p2), 5.0, epsilon = 1e-10);
}
2. 集成测试
创建 tests/geometry_test.rs
:
use mylib::geometry::Point;#[test]
fn test_point_creation() {let p = Point::new(1.0, 2.0);assert_eq!(p.x, 1.0);assert_eq!(p.y, 2.0);
}
3. 基准测试
// benches/benchmarks.rs
#![feature(test)]
extern crate test;
use test::Bencher;#[bench]
fn bench_factorial(b: &mut Bencher) {b.iter(|| factorial(20));
}
运行基准测试:
cargo bench
发布到 crates.io
1. 准备发布
cargo login <your-api-token>
cargo publish --dry-run
2. 检查包
cargo package
3. 发布
cargo publish
高级主题
1. FFI 接口 (C API)
// src/ffi.rs
use std::os::raw::c_int;#[no_mangle]
pub extern "C" fn rust_add(a: c_int, b: c_int) -> c_int {a + b
}
2. 条件编译
#[cfg(target_os = "linux")]
fn platform_specific() {println!("Running on Linux!");
}#[cfg(feature = "serde")]
impl Serialize for Point {// ...
}
3. 错误处理最佳实践
use thiserror::Error;#[derive(Error, Debug)]
pub enum GeometryError {#[error("invalid point coordinates: ({0}, {1})")]InvalidPoint(f64, f64),#[error("points are coincident")]CoincidentPoints,
}pub fn calculate_slope(p1: &Point, p2: &Point) -> Result<f64, GeometryError> {if p1 == p2 {return Err(GeometryError::CoincidentPoints);}Ok((p2.y - p1.y) / (p2.x - p1.x))
}
最佳实践
-
模块化设计:
mylib/ ├── src/ │ ├── lib.rs │ ├── math.rs │ ├── geometry.rs │ ├── shapes.rs │ └── ffi.rs
-
文档驱动开发:
- 为所有公共项编写文档
- 包含使用示例
-
全面的测试:
- 单元测试覆盖所有函数
- 集成测试验证模块交互
- 基准测试关键路径
-
版本管理:
- 遵循语义化版本控制 (SemVer)
- 使用
cargo semver-checks
验证兼容性
-
持续集成:
# .github/workflows/ci.yml name: CIon: [push, pull_request]jobs:build:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v2- name: Buildrun: cargo build --all-features- name: Testrun: cargo test --all-features- name: Checkrun: cargo check- name: Clippyrun: cargo clippy --all-targets --all-features -- -D warnings- name: Formatrun: cargo fmt -- --check
性能优化技巧
-
使用内联:
#[inline(always)] pub fn fast_add(a: i32, b: i32) -> i32 {a + b }
-
避免不必要的拷贝:
pub fn process_points(points: &[Point]) {// 使用引用而不是所有权 }
-
利用迭代器:
pub fn sum_of_squares(numbers: &[i32]) -> i32 {numbers.iter().map(|x| x * x).sum() }
-
使用零成本抽象:
pub fn generic_add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {a + b }
通过遵循这些实践,您可以创建高质量、可维护且高性能的 Rust 库,为 Rust 生态系统做出贡献。