Rust 学习(4)-函数与注释 文章目录一、回顾与导入二、函数基础函数定义与命名参数传递三、语句 vs 表达式 —— 核心概念四、函数返回值方式一使用 return 关键字早期返回方式二隐式返回表达式返回多个值使用元组返回类型 - ()空元组五、常见错误与陷阱陷阱 1忘记在最后一个表达式加分号会导致不同行为陷阱 2分号的位置决定了是语句还是表达式六、注释三种注释风格1. 普通注释2. 文档注释 ///3. 内部文档注释 //!文档注释测试七、完整代码示例八、总结与速查九、思考题参考链接返回首页 | 上篇 | 下篇掌握 Rust 函数的核心语法 —— 表达式、返回值与三种注释一、回顾与导入前几篇我们学习了变量、可变性、常量与 shadowing基础数据类型标量与复合类型今天我们来学习 Rust 中的函数。函数在 Rust 中无处不在 ——main函数就是程序的入口。Rust 的函数设计有一些独特的特性比如表达式 vs 语句掌握这些会帮你写出更地道的 Rust 代码。二、函数基础函数定义与命名使用fn关键字定义函数命名采用snake_case风格fnmain(){println!(Hello from main!);say_hello();print_number(42);}fnsay_hello(){println!(Hello, world!);}fnprint_number(x:i32){println!(The number is: {},x);}参数传递Rust 函数的参数必须显式声明类型编译器不会推断函数签名中的类型fnmain(){print_labeled_measurement(10,m);}fnprint_labeled_measurement(value:i32,unit_label:char){println!(The measurement is: {}{},value,unit_label);}三、语句 vs 表达式 —— 核心概念这是 Rust 中一个非常重要的区别概念特点例子返回值语句Statement执行操作不返回值let x 5;无()表达式Expression计算结果值5 3、x 1、函数调用有值核心规则语句以分号;结尾表达式不以分号结尾加了分号就变成语句了fnmain(){// 语句letx5;// 这是一个语句不返回值// 表达式lety{// 代码块也是表达式返回最后一个表达式的值leta3;letb4;ab// 没有分号这是一个表达式};println!(y {},y);// y 7// 表达式可以作为函数调用的参数println!({},53);// 5 3 是一个表达式值为 8// 注意加上了分号就会变成语句letz{leta3;a1;// 这里有分号变成了语句值为 ()};println!(z {:?},z);// z ()}四、函数返回值函数可以通过两种方式返回值方式一使用return关键字早期返回fnis_even(x:i32)-bool{ifx%20{returntrue;// 早期返回}false// 隐式返回表达式}方式二隐式返回表达式函数体中最后一个表达式的值会作为返回值不需要return关键字fnadd(a:i32,b:i32)-i32{ab// 没有分号这是表达式作为返回值}fnmain(){letresultadd(5,3);println!(5 3 {},result);}返回多个值使用元组fnswap(x:i32,y:i32)-(i32,i32){(y,x)// 返回元组}fnmain(){let(a,b)swap(10,20);println!(a {}, b {},a,b);// a 20, b 10}返回类型- ()空元组如果函数没有返回值实际上是返回了空元组()fndo_nothing(){// 隐式返回 ()}// 等价于fndo_nothing_explicit()-(){return();}五、常见错误与陷阱陷阱 1忘记在最后一个表达式加分号会导致不同行为// 错误示范 - 本意是返回 5fnwrong()-i32{5;// 加上了分号变成了语句返回值变成了 ()}// error[E0308]: mismatched types, expected i32, found ()// 正确写法fncorrect()-i32{5// 没有分号}陷阱 2分号的位置决定了是语句还是表达式fnmain(){// 这是两个语句letx5;lety6;// 这是一个表达式整个代码块的值为 7letz{leta3;letb4;ab// 没有分号};println!(z {},z);// 如果代码块最后加分号返回 ()letw{leta3;letb4;ab;// 有分号};println!(w {:?},w);// ()}六、注释三种注释风格Rust 提供了三种注释类型语法用途是否生成文档普通注释//或/* */代码说明、临时禁用❌文档注释///为接下来的项生成文档✅内部文档注释//!为父级项如 crate生成文档✅1. 普通注释// 单行注释/* 多行注释 可以跨越多行 */fnmain(){letx5;// 行尾注释// let y 10; // 可以用注释临时禁用代码}2. 文档注释///用于函数、结构体、枚举等支持 Markdown 格式/// 计算两个整数的和////// # Examples////// /// let result add(2, 3);/// assert_eq!(result, 5);/// ////// # Panics////// 这个函数不会 panicpubfnadd(a:i32,b:i32)-i32{ab}运行cargo doc --open可以生成并打开 HTML 文档。3. 内部文档注释//!用于模块或整个 crate 的顶层文档通常放在lib.rs或main.rs的开头//! # 我的计算库//!//! 这个库提供了一些基本的数学运算函数。//!//! ## 快速开始//!//! //! use my_lib::add;//!//! let result add(1, 2);//! pubfnadd(a:i32,b:i32)-i32{ab}文档注释测试文档注释中的代码块会自动作为测试运行/// 将字符串转换为整数////// # Examples////// /// let result to_number(42);/// assert_eq!(result, 42);/// fnto_number(s:str)-i32{s.parse().unwrap()}运行cargo test时会执行这些示例代码。七、完整代码示例//! # 函数与注释示例//!//! 这个程序演示了 Rust 中的函数定义、返回值、表达式与语句的区别//! 以及三种注释风格的使用。/// 问候函数////// 向指定名称的人打招呼。////// # Arguments////// * name - 人的名字////// # Examples////// /// let message greet(Rust);/// assert_eq!(message, Hello, Rust!);/// fngreet(name:str)-String{format!(Hello, {}!,name)// 隐式返回}/// 计算一个数的阶乘使用循环////// 返回值是 n!如果 n 为 0 则返回 1。fnfactorial(n:u64)-u64{letmutresult1;foriin1..n{result*i;}result}/// 用表达式写一个更简洁的阶乘使用递归fnfactorial_expr(n:u64)-u64{ifn0{1}else{n*factorial_expr(n-1)}// if 是表达式返回分支的值}/// 返回两个值的和与积fnsum_and_product(a:i32,b:i32)-(i32,i32){(ab,a*b)// 返回元组}fnmain(){// 普通注释演示函数调用letgreetinggreet(Rust Learner);println!({},greeting);// 演示阶乘letn5;println!({}! {},n,factorial(n));println!({}! (expr) {},n,factorial_expr(n));// 演示返回元组let(sum,product)sum_and_product(10,20);println!(10 20 {}, 10 * 20 {},sum,product);// 演示表达式与语句的区别letexpr_result{letx10;lety20;xy// 表达式值为 30};println!(代码块表达式返回: {},expr_result);letstmt_result{letx10;lety20;xy;// 语句返回 ()};println!(代码块语句返回: {:?},stmt_result);}cargo doc生成的文档, 位于target/doc/xxx/index.html八、总结与速查知识点语法示例定义函数fn name(param: Type) - ReturnTypefn add(x: i32, y: i32) - i32语句以分号结尾不返回值let x 5;表达式不以分号结尾有值5 3、{ let x1; x1 }隐式返回函数体最后一个表达式a b显式返回return value;return 42;无返回值- ()或省略fn do_nothing()普通注释//或/* */// 这是一条注释文档注释////// 函数说明内部文档//!//! crate 文档核心要点✅ 函数参数必须声明类型✅ 区分语句有分号不返回值和表达式无分号返回值✅ 隐式返回是 Rust 风格只有需要早期返回时才用return✅ 用///写文档注释用cargo doc生成文档九、思考题下面代码会输出什么fnmain(){letx{lety42;println!(y {},y);y};println!(x {},x);}如果没有显式返回函数如何返回多个值为什么 Rust 要区分语句和表达式提示这和其他语言如 C/Java有什么不同参考链接Rust Book - FunctionsRust Book - CommentsRustdoc BookRust by Example - Functions返回首页 | 上篇 | 下篇