Rust 练习册 :Phone Number与电话号码处理

电话号码处理是现代软件开发中常见的需求,特别是在通讯、社交、电商等应用中。在 Exercism 的 "phone-number" 练习中,我们需要实现一个函数来清理和验证北美电话号码(NANP - North American Numbering Plan)。这不仅能帮助我们掌握字符串处理和正则表达式技巧,还能深入学习Rust中的错误处理和数据验证。

什么是北美电话号码?

北美电话号码遵循北美编号计划(NANP),格式为:(NXX) NXX-XXXX,其中:

  • 第一部分(3位)是地区代码(Area Code)
  • 第二部分(3位)是交换代码(Exchange Code)
  • 第三部分(4位)是号码(Number)

有效的NANP电话号码需要满足以下条件:

  1. 总共10位数字(不包括国家代码)
  2. 如果有11位数字,第一位必须是1(美国国家代码)
  3. 地区代码不能以0或1开头
  4. 交换代码不能以0或1开头

让我们先看看练习提供的函数签名:

rust 复制代码
pub fn number(user_number: &str) -> Option<String> {
    unimplemented!(
        "Given the number entered by user '{}', convert it into SMS-friendly format. If the entered number is not a valid NANP number, return None.",
        user_number
    );
}

我们需要实现number函数,将用户输入的电话号码转换为标准格式,如果输入无效则返回None。

设计分析

1. 核心要求

  1. 数据清理:从用户输入中提取数字,去除所有非数字字符
  2. 格式验证:验证电话号码是否符合NANP标准
  3. 长度检查:检查电话号码长度是否正确
  4. 数字验证:验证地区代码和交换代码的首位不能是0或1

2. 技术要点

  1. 字符串处理:高效处理和过滤字符串中的字符
  2. 正则表达式:使用正则表达式进行模式匹配和提取
  3. 错误处理:使用Option类型处理无效输入
  4. 数据验证:实现复杂的业务规则验证

完整实现

1. 基础实现

rust 复制代码
pub fn number(user_number: &str) -> Option<String> {
    // 提取所有数字字符
    let digits: String = user_number.chars().filter(|c| c.is_ascii_digit()).collect();
    
    // 根据数字长度进行处理
    match digits.len() {
        10 => {
            // 检查地区代码和交换代码
            if is_valid_area_code(&digits[0..3]) && is_valid_exchange_code(&digits[3..6]) {
                Some(digits)
            } else {
                None
            }
        }
        11 => {
            // 检查第一位是否为1
            if digits.starts_with('1') {
                let number_part = &digits[1..];
                if is_valid_area_code(&number_part[0..3]) && is_valid_exchange_code(&number_part[3..6]) {
                    Some(number_part.to_string())
                } else {
                    None
                }
            } else {
                None
            }
        }
        _ => None,
    }
}

fn is_valid_area_code(area_code: &str) -> bool {
    // 地区代码不能以0或1开头
    !area_code.starts_with('0') && !area_code.starts_with('1')
}

fn is_valid_exchange_code(exchange_code: &str) -> bool {
    // 交换代码不能以0或1开头
    !exchange_code.starts_with('0') && !exchange_code.starts_with('1')
}

2. 优化实现

rust 复制代码
pub fn number(user_number: &str) -> Option<String> {
    // 提取所有数字字符
    let digits: String = user_number.chars().filter(|c| c.is_ascii_digit()).collect();
    
    // 验证并处理电话号码
    validate_and_format(digits)
}

fn validate_and_format(digits: String) -> Option<String> {
    match digits.len() {
        10 => {
            // 直接验证10位号码
            validate_ten_digit_number(&digits)
        }
        11 => {
            // 验证11位号码,第一位必须是1
            if digits.starts_with('1') {
                validate_ten_digit_number(&digits[1..])
            } else {
                None
            }
        }
        _ => None,
    }
}

fn validate_ten_digit_number(digits: &str) -> Option<String> {
    // 检查地区代码(前3位)和交换代码(第4-6位)
    let area_code = &digits[0..3];
    let exchange_code = &digits[3..6];
    
    if is_valid_area_code(area_code) && is_valid_exchange_code(exchange_code) {
        Some(digits.to_string())
    } else {
        None
    }
}

fn is_valid_area_code(area_code: &str) -> bool {
    // 地区代码不能以0或1开头
    !area_code.starts_with('0') && !area_code.starts_with('1')
}

fn is_valid_exchange_code(exchange_code: &str) -> bool {
    // 交换代码不能以0或1开头
    !exchange_code.starts_with('0') && !exchange_code.starts_with('1')
}

3. 使用正则表达式的实现

rust 复制代码
pub fn number(user_number: &str) -> Option<String> {
    use regex::Regex;
    
    // 移除所有非数字字符
    let re = Regex::new(r"\D").unwrap();
    let digits = re.replace_all(user_number, "").to_string();
    
    // 验证并格式化电话号码
    validate_and_format(digits)
}

fn validate_and_format(digits: String) -> Option<String> {
    match digits.len() {
        10 => {
            validate_ten_digit_number(&digits)
        }
        11 => {
            if digits.starts_with('1') {
                validate_ten_digit_number(&digits[1..])
            } else {
                None
            }
        }
        _ => None,
    }
}

fn validate_ten_digit_number(digits: &str) -> Option<String> {
    let area_code = &digits[0..3];
    let exchange_code = &digits[3..6];
    
    if is_valid_area_code(area_code) && is_valid_exchange_code(exchange_code) {
        Some(digits.to_string())
    } else {
        None
    }
}

fn is_valid_area_code(area_code: &str) -> bool {
    !area_code.starts_with('0') && !area_code.starts_with('1')
}

fn is_valid_exchange_code(exchange_code: &str) -> bool {
    !exchange_code.starts_with('0') && !exchange_code.starts_with('1')
}

测试用例分析

通过查看测试用例,我们可以更好地理解需求:

rust 复制代码
#[test]
fn test_cleans_the_number() {
    process_clean_case("(223) 456-7890", Some("2234567890"));
}

应该清理括号、空格和连字符等字符。

rust 复制代码
#[test]
fn test_cleans_numbers_with_dots() {
    process_clean_case("223.456.7890", Some("2234567890"));
}

应该清理点号等分隔符。

rust 复制代码
#[test]
fn test_cleans_numbers_with_multiple_spaces() {
    process_clean_case("223 456   7890   ", Some("2234567890"));
}

应该清理多余的空格。

rust 复制代码
#[test]
fn test_invalid_when_9_digits() {
    process_clean_case("123456789", None);
}

9位数字是无效的。

rust 复制代码
#[test]
fn test_invalid_when_11_digits_does_not_start_with_a_1() {
    process_clean_case("22234567890", None);
}

11位数字但不以1开头是无效的。

rust 复制代码
#[test]
fn test_valid_when_11_digits_and_starting_with_1() {
    process_clean_case("12234567890", Some("2234567890"));
}

11位数字且以1开头是有效的,应移除前导1。

rust 复制代码
#[test]
fn test_valid_when_11_digits_and_starting_with_1_even_with_punctuation() {
    process_clean_case("+1 (223) 456-7890", Some("2234567890"));
}

带有标点符号的11位数字且以+1开头是有效的。

rust 复制代码
#[test]
fn test_invalid_when_more_than_11_digits() {
    process_clean_case("321234567890", None);
}

超过11位数字是无效的。

rust 复制代码
#[test]
fn test_invalid_with_letters() {
    process_clean_case("123-abc-7890", None);
}

包含字母是无效的。

rust 复制代码
#[test]
fn test_invalid_with_punctuations() {
    process_clean_case("123-@:!-7890", None);
}

包含特殊标点符号是无效的。

rust 复制代码
#[test]
fn test_invalid_if_area_code_starts_with_1_on_valid_11digit_number() {
    process_clean_case("1 (123) 456-7890", None);
}

地区代码以1开头是无效的。

rust 复制代码
#[test]
fn test_invalid_if_area_code_starts_with_0_on_valid_11digit_number() {
    process_clean_case("1 (023) 456-7890", None);
}

地区代码以0开头是无效的。

rust 复制代码
#[test]
fn test_invalid_if_area_code_starts_with_1() {
    process_clean_case("(123) 456-7890", None);
}

地区代码以1开头是无效的。

rust 复制代码
#[test]
fn test_invalid_if_exchange_code_starts_with_1() {
    process_clean_case("(223) 156-7890", None);
}

交换代码以1开头是无效的。

rust 复制代码
#[test]
fn test_invalid_if_exchange_code_starts_with_0() {
    process_clean_case("(223) 056-7890", None);
}

交换代码以0开头是无效的。

rust 复制代码
#[test]
fn test_invalid_if_exchange_code_starts_with_1_on_valid_11digit_number() {
    process_clean_case("1 (223) 156-7890", None);
}

交换代码以1开头是无效的。

rust 复制代码
#[test]
fn test_invalid_if_exchange_code_starts_with_0_on_valid_11digit_number() {
    process_clean_case("1 (223) 056-7890", None);
}

交换代码以0开头是无效的。

rust 复制代码
#[test]
fn test_invalid_if_area_code_starts_with_0() {
    process_clean_case("(023) 456-7890", None);
}

地区代码以0开头是无效的。

性能优化版本

考虑性能的优化实现:

rust 复制代码
pub fn number(user_number: &str) -> Option<String> {
    // 预分配字符串容量以避免重新分配
    let mut digits = String::with_capacity(11);
    
    // 手动迭代字符以提高性能
    for c in user_number.chars() {
        if c.is_ascii_digit() {
            digits.push(c);
        }
    }
    
    // 验证并格式化电话号码
    validate_and_format_optimized(digits)
}

fn validate_and_format_optimized(digits: String) -> Option<String> {
    match digits.len() {
        10 => {
            validate_ten_digit_number_optimized(&digits)
        }
        11 => {
            // 检查第一位是否为1(使用索引而不是starts_with以提高性能)
            if unsafe { digits.as_bytes().get_unchecked(0) == &b'1' } {
                validate_ten_digit_number_optimized(&digits[1..])
            } else {
                None
            }
        }
        _ => None,
    }
}

fn validate_ten_digit_number_optimized(digits: &str) -> Option<String> {
    // 使用字节比较以提高性能
    let bytes = digits.as_bytes();
    
    // 检查地区代码(前3位)首位不能是0或1
    if bytes[0] == b'0' || bytes[0] == b'1' {
        return None;
    }
    
    // 检查交换代码(第4-6位)首位不能是0或1
    if bytes[3] == b'0' || bytes[3] == b'1' {
        return None;
    }
    
    Some(digits.to_string())
}

// 使用预编译正则表达式的版本
use regex::Regex;
use std::sync::OnceLock;

fn get_digit_regex() -> &'static Regex {
    static REGEX: OnceLock<Regex> = OnceLock::new();
    REGEX.get_or_init(|| Regex::new(r"\D").unwrap())
}

pub fn number_with_regex(user_number: &str) -> Option<String> {
    let re = get_digit_regex();
    let digits = re.replace_all(user_number, "").to_string();
    validate_and_format_optimized(digits)
}

错误处理和边界情况

考虑更多边界情况的实现:

rust 复制代码
pub fn number(user_number: &str) -> Option<String> {
    // 处理空字符串
    if user_number.is_empty() {
        return None;
    }
    
    // 提取所有数字字符
    let digits: String = user_number.chars().filter(|c| c.is_ascii_digit()).collect();
    
    // 处理没有数字的情况
    if digits.is_empty() {
        return None;
    }
    
    // 验证并格式化电话号码
    validate_and_format_with_error_handling(digits)
}

fn validate_and_format_with_error_handling(digits: String) -> Option<String> {
    match digits.len() {
        10 => {
            validate_ten_digit_number_with_error_handling(&digits)
        }
        11 => {
            if digits.starts_with('1') {
                validate_ten_digit_number_with_error_handling(&digits[1..])
            } else {
                None
            }
        }
        _ => None,
    }
}

fn validate_ten_digit_number_with_error_handling(digits: &str) -> Option<String> {
    let area_code = &digits[0..3];
    let exchange_code = &digits[3..6];
    
    // 更详细的验证
    if !is_valid_area_code_detailed(area_code) {
        return None;
    }
    
    if !is_valid_exchange_code_detailed(exchange_code) {
        return None;
    }
    
    Some(digits.to_string())
}

fn is_valid_area_code_detailed(area_code: &str) -> bool {
    // 地区代码不能以0或1开头
    if area_code.starts_with('0') || area_code.starts_with('1') {
        return false;
    }
    
    // 额外的业务规则可以在这里添加
    true
}

fn is_valid_exchange_code_detailed(exchange_code: &str) -> bool {
    // 交换代码不能以0或1开头
    if exchange_code.starts_with('0') || exchange_code.starts_with('1') {
        return false;
    }
    
    // 额外的业务规则可以在这里添加
    true
}

// 返回详细错误信息的版本
#[derive(Debug, PartialEq)]
pub enum PhoneNumberError {
    InvalidLength,
    InvalidCountryCode,
    InvalidAreaCode,
    InvalidExchangeCode,
    NoDigits,
}

impl std::fmt::Display for PhoneNumberError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            PhoneNumberError::InvalidLength => write!(f, "电话号码长度无效"),
            PhoneNumberError::InvalidCountryCode => write!(f, "国家代码无效"),
            PhoneNumberError::InvalidAreaCode => write!(f, "地区代码无效"),
            PhoneNumberError::InvalidExchangeCode => write!(f, "交换代码无效"),
            PhoneNumberError::NoDigits => write!(f, "未找到数字"),
        }
    }
}

impl std::error::Error for PhoneNumberError {}

pub fn number_detailed(user_number: &str) -> Result<String, PhoneNumberError> {
    // 处理空字符串
    if user_number.is_empty() {
        return Err(PhoneNumberError::NoDigits);
    }
    
    // 提取所有数字字符
    let digits: String = user_number.chars().filter(|c| c.is_ascii_digit()).collect();
    
    // 处理没有数字的情况
    if digits.is_empty() {
        return Err(PhoneNumberError::NoDigits);
    }
    
    // 验证并格式化电话号码
    validate_and_format_detailed(digits)
}

fn validate_and_format_detailed(digits: String) -> Result<String, PhoneNumberError> {
    match digits.len() {
        10 => {
            validate_ten_digit_number_detailed(&digits)
        }
        11 => {
            if digits.starts_with('1') {
                validate_ten_digit_number_detailed(&digits[1..])
            } else {
                Err(PhoneNumberError::InvalidCountryCode)
            }
        }
        _ => Err(PhoneNumberError::InvalidLength),
    }
}

fn validate_ten_digit_number_detailed(digits: &str) -> Result<String, PhoneNumberError> {
    let area_code = &digits[0..3];
    let exchange_code = &digits[3..6];
    
    if area_code.starts_with('0') || area_code.starts_with('1') {
        return Err(PhoneNumberError::InvalidAreaCode);
    }
    
    if exchange_code.starts_with('0') || exchange_code.starts_with('1') {
        return Err(PhoneNumberError::InvalidExchangeCode);
    }
    
    Ok(digits.to_string())
}

扩展功能

基于基础实现,我们可以添加更多功能:

rust 复制代码
pub struct PhoneNumber {
    digits: String,
}

impl PhoneNumber {
    pub fn new(user_number: &str) -> Option<Self> {
        number(user_number).map(|digits| PhoneNumber { digits })
    }
    
    pub fn new_unchecked(digits: String) -> Self {
        PhoneNumber { digits }
    }
    
    pub fn area_code(&self) -> &str {
        &self.digits[0..3]
    }
    
    pub fn exchange_code(&self) -> &str {
        &self.digits[3..6]
    }
    
    pub fn number(&self) -> &str {
        &self.digits[6..]
    }
    
    pub fn full_number(&self) -> &str {
        &self.digits
    }
    
    pub fn to_formatted_string(&self) -> String {
        format!("({}) {}-{}", 
                self.area_code(), 
                self.exchange_code(), 
                self.number())
    }
    
    pub fn is_valid(&self) -> bool {
        self.digits.len() == 10 && 
        is_valid_area_code(self.area_code()) && 
        is_valid_exchange_code(self.exchange_code())
    }
}

pub fn number(user_number: &str) -> Option<String> {
    let digits: String = user_number.chars().filter(|c| c.is_ascii_digit()).collect();
    validate_and_format(digits)
}

fn validate_and_format(digits: String) -> Option<String> {
    match digits.len() {
        10 => {
            validate_ten_digit_number(&digits)
        }
        11 => {
            if digits.starts_with('1') {
                validate_ten_digit_number(&digits[1..])
            } else {
                None
            }
        }
        _ => None,
    }
}

fn validate_ten_digit_number(digits: &str) -> Option<String> {
    let area_code = &digits[0..3];
    let exchange_code = &digits[3..6];
    
    if is_valid_area_code(area_code) && is_valid_exchange_code(exchange_code) {
        Some(digits.to_string())
    } else {
        None
    }
}

fn is_valid_area_code(area_code: &str) -> bool {
    !area_code.starts_with('0') && !area_code.starts_with('1')
}

fn is_valid_exchange_code(exchange_code: &str) -> bool {
    !exchange_code.starts_with('0') && !exchange_code.starts_with('1')
}

// 电话号码验证器
pub struct PhoneNumberValidator;

impl PhoneNumberValidator {
    pub fn new() -> Self {
        PhoneNumberValidator
    }
    
    pub fn validate(&self, user_number: &str) -> Option<PhoneNumber> {
        PhoneNumber::new(user_number)
    }
    
    pub fn is_valid(&self, user_number: &str) -> bool {
        self.validate(user_number).is_some()
    }
    
    // 批量验证电话号码
    pub fn validate_batch(&self, numbers: &[&str]) -> Vec<(String, bool)> {
        numbers
            .iter()
            .map(|&number| {
                let is_valid = self.is_valid(number);
                (number.to_string(), is_valid)
            })
            .collect()
    }
    
    // 查找有效的电话号码
    pub fn find_valid_numbers(&self, numbers: &[&str]) -> Vec<String> {
        numbers
            .iter()
            .filter_map(|&number| self.validate(number))
            .map(|phone| phone.full_number().to_string())
            .collect()
    }
    
    // 格式化电话号码(如果有效)
    pub fn format_if_valid(&self, user_number: &str) -> Option<String> {
        self.validate(user_number)
            .map(|phone| phone.to_formatted_string())
    }
}

// 电话号码分析器
pub struct PhoneNumberAnalysis {
    pub original_input: String,
    pub cleaned_number: Option<String>,
    pub is_valid: bool,
    pub area_code: Option<String>,
    pub exchange_code: Option<String>,
    pub number_part: Option<String>,
    pub formatted_number: Option<String>,
}

impl PhoneNumberValidator {
    pub fn analyze(&self, user_number: &str) -> PhoneNumberAnalysis {
        let cleaned_number = number(user_number);
        
        let (area_code, exchange_code, number_part, formatted_number) = 
            if let Some(ref phone) = cleaned_number {
                let phone_obj = PhoneNumber::new_unchecked(phone.clone());
                (
                    Some(phone_obj.area_code().to_string()),
                    Some(phone_obj.exchange_code().to_string()),
                    Some(phone_obj.number().to_string()),
                    Some(phone_obj.to_formatted_string()),
                )
            } else {
                (None, None, None, None)
            };
        
        PhoneNumberAnalysis {
            original_input: user_number.to_string(),
            cleaned_number,
            is_valid: cleaned_number.is_some(),
            area_code,
            exchange_code,
            number_part,
            formatted_number,
        }
    }
}

// 便利函数
pub fn format_phone_number(user_number: &str) -> Option<String> {
    let validator = PhoneNumberValidator::new();
    validator.format_if_valid(user_number)
}

pub fn is_valid_phone_number(user_number: &str) -> bool {
    let validator = PhoneNumberValidator::new();
    validator.is_valid(user_number)
}

实际应用场景

电话号码处理在实际开发中有以下应用:

  1. 通讯应用:电话、短信、视频通话应用
  2. 电商平台:用户注册、订单联系信息
  3. 社交网络:用户资料、好友联系
  4. 金融服务:银行、支付应用的用户验证
  5. 医疗健康:预约系统、患者联系
  6. 物流配送:快递、外卖的联系信息
  7. 企业管理系统:客户关系管理、员工信息
  8. 政府服务:公共服务、政务应用

算法复杂度分析

  1. 时间复杂度:O(n)

    • 其中n是输入字符串的长度,需要遍历每个字符
  2. 空间复杂度:O(n)

    • 需要存储提取的数字字符

与其他实现方式的比较

rust 复制代码
// 使用nom解析器的实现
use nom::{
    character::complete::{digit1, char},
    combinator::{opt, map_res},
    sequence::{delimited, tuple},
    multi::many0,
    bytes::complete::tag,
    IResult,
};

pub fn number_nom(user_number: &str) -> Option<String> {
    // 使用nom解析器库实现电话号码解析
    // 这里只是一个示例,实际实现会更复杂
    unimplemented!()
}

// 使用功能完整的电话号码库实现
// [dependencies]
// phonenumber = "0.3"

pub fn number_phonenumber_lib(user_number: &str) -> Option<String> {
    use phonenumber::Mode;
    
    match phonenumber::parse(None, user_number) {
        Ok(phone_number) => {
            if phonenumber::is_valid(&phone_number) {
                Some(phonenumber::format(&phone_number, Mode::E164)[1..].to_string()) // 移除+号
            } else {
                None
                }
        }
        Err(_) => None,
    }
}

// 使用状态机的实现
#[derive(Debug, Clone, Copy)]
enum ParseState {
    Start,
    ReadingCountryCode,
    ReadingAreaCode,
    ReadingExchangeCode,
    ReadingNumber,
    Done,
    Error,
}

pub fn number_state_machine(user_number: &str) -> Option<String> {
    let mut state = ParseState::Start;
    let mut digits = String::new();
    
    for c in user_number.chars() {
        match state {
            ParseState::Start => {
                if c.is_ascii_digit() {
                    digits.push(c);
                    if digits.len() == 1 && c == '1' {
                        state = ParseState::ReadingCountryCode;
                    } else {
                        state = ParseState::ReadingAreaCode;
                    }
                }
                // 忽略非数字字符
            }
            ParseState::ReadingCountryCode => {
                if c.is_ascii_digit() {
                    digits.push(c);
                    state = ParseState::ReadingAreaCode;
                }
            }
            ParseState::ReadingAreaCode => {
                if c.is_ascii_digit() {
                    digits.push(c);
                    if digits.len() == 3 {
                        state = ParseState::ReadingExchangeCode;
                    }
                }
            }
            ParseState::ReadingExchangeCode => {
                if c.is_ascii_digit() {
                    digits.push(c);
                    if digits.len() == 6 {
                        state = ParseState::ReadingNumber;
                    }
                }
            }
            ParseState::ReadingNumber => {
                if c.is_ascii_digit() {
                    digits.push(c);
                    if digits.len() == 10 {
                        state = ParseState::Done;
                    }
                }
            }
            ParseState::Done | ParseState::Error => {
                if c.is_ascii_digit() {
                    // 超过10位数字
                    state = ParseState::Error;
                }
            }
        }
    }
    
    if state == ParseState::Done || (state == ParseState::ReadingNumber && digits.len() == 10) {
        Some(digits)
    } else {
        None
    }
}

// 使用外部API验证的实现
// [dependencies]
// reqwest = "0.11"
// tokio = { version = "1", features = ["full"] }

pub async fn number_with_api_validation(user_number: &str) -> Option<String> {
    let cleaned_number = number(user_number)?;
    
    // 这里可以调用外部API验证电话号码是否真实存在
    // let client = reqwest::Client::new();
    // let response = client
    //     .post("https://api.phonenumberverification.com/validate")
    //     .json(&serde_json::json!({"number": cleaned_number}))
    //     .send()
    //     .await;
    // 
    // if let Ok(resp) = response {
    //     if resp.status().is_success() {
    //         return Some(cleaned_number);
    //     }
    // }
    
    Some(cleaned_number) // 为示例直接返回
}

总结

通过 phone-number 练习,我们学到了:

  1. 字符串处理:掌握了从复杂字符串中提取和验证数据的技巧
  2. 正则表达式:学会了使用正则表达式进行模式匹配和数据提取
  3. 错误处理:深入理解了Option和Result类型在数据验证中的应用
  4. 业务规则实现:了解了如何将复杂的业务规则转换为代码实现
  5. 性能优化:学会了预分配内存和使用高效算法等优化技巧
  6. 数据封装:理解了如何设计结构体来封装和操作复杂数据

这些技能在实际开发中非常有用,特别是在数据处理、表单验证、用户输入处理等场景中。电话号码处理虽然是一个具体的应用问题,但它涉及到了字符串处理、正则表达式、错误处理、业务规则实现等许多核心概念,是学习Rust实用编程的良好起点。

通过这个练习,我们也看到了Rust在数据处理和验证方面的强大能力,以及如何用安全且高效的方式实现复杂的业务规则。这种结合了安全性和性能的语言特性正是Rust的魅力所在。

相关推荐
one year.2 小时前
Linux:线程同步与互斥
java·开发语言
一 乐2 小时前
旅游|内蒙古景点旅游|基于Springboot+Vue的内蒙古景点旅游管理系统设计与实现(源码+数据库+文档)
开发语言·前端·数据库·vue.js·spring boot·后端·旅游
不爱编程的小九九2 小时前
小九源码-springboot103-踏雪阁民宿订购平台
java·开发语言·spring boot
共享家95272 小时前
LRU 缓存的设计与实现
开发语言·c++
2301_796512523 小时前
Rust编程学习 - 问号运算符会return一个Result 类型,但是如何使用main函数中使用问号运算符
开发语言·学习·算法·rust
座山雕~3 小时前
测试接口-----详细
开发语言·postman
小龙报3 小时前
算法通关指南:数据结构和算法篇 --- 队列相关算法题》--- 1. 【模板】队列,2. 机器翻译
c语言·开发语言·数据结构·c++·算法·学习方法·visual studio
木木em哈哈3 小时前
有关于cnb自动化的脚本补全
服务器·开发语言·pygame
星释3 小时前
Rust 练习册 :Poker与扑克牌游戏
开发语言·游戏·rust