跟着谷歌团队学Rust - Functions详细入门

大家好,我是梦兽编程。欢迎回来与梦兽编程一起刷Rust的系列。

这是由 Google 的 Android开发团队的分享Rust课程。本课程涵盖了 Rust 的方方面面,从基本语法到泛型和错误处理等高级主题。

该课程的最新版本可以在 google.github.io/comprehensi...

如果你喜欢看梦兽编程的版本可以订阅跟着谷歌安卓团队学Rust订阅最新内容,梦兽编程也期待大家关注我的个人网站。

加入梦兽编程微信群juejin.cn/user/206673...

函数

Rust 中的函数是将代码块封装起来,并可以重复使用的代码块。函数可以接受参数,并返回值。

php 复制代码
fn <函数名>(<参数列表>) -> <返回值类型> {
    // 函数体
}

模块中的函数体定义

当然以上是非常简单的函数定义,在一些模块中封装函数体你还需要加入mod,等学习到rust模块的时候再详细现在知道这个概念就好了:

rust 复制代码
mod math {
    pub fn add_two(x: i32, y: i32) -> i32 {
        x + y
    }
}

结构体中的函数体

在Rust和golang这一类现代语言中,结构体有点类似于Java中的class,你可以类比成方法即可:

rust 复制代码
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }

    fn inc_width(&mut self, delta: u32) {
        self.width += delta;
    }
}

fn main() {
    let mut rect = Rectangle { width: 10, height: 5 };
    println!("old area: {}", rect.area());
    rect.inc_width(5);
    println!("new area: {}", rect.area());
}

"

如果你喜欢使用new的写法可以在结构体中添加new的方法

arduino 复制代码
fn new(width: u32, height: u32) -> Rectangle {
    Rectangle { width, height }
}

如何使用Rectangle::new进行调用。

著名的FizzBuzz面试问题的Rust版本:

rust 复制代码
fn main() {
    print_fizzbuzz_to(20);
}

fn is_divisible(n: u32, divisor: u32) -> bool {
    if divisor == 0 {
        return false;
    }
    n % divisor == 0
}

fn fizzbuzz(n: u32) -> String {
    let fizz = if is_divisible(n, 3) { "fizz" } else { "" };
    let buzz = if is_divisible(n, 5) { "buzz" } else { "" };
    if fizz.is_empty() && buzz.is_empty() {
        return format!("{n}");
    }
    format!("{fizz}{buzz}")
}

fn print_fizzbuzz_to(n: u32) {
    for i in 1..=n {
        println!("{}", fizzbuzz(i));
    }
}

我们在main中引用了下面写的一个函数。前向声明都都是可以的。不需要和某些语言一样需要先定义才能使用。

声明参数后面是类型(与某些编程语言相反),然后是返回类型。

函数体(或任何块)中的最后一个表达式成为返回值。只需省略表达式末尾的;即可。

"

有点类似与js 的箭头函数的简写 () => value rust: (n:u32) -> string { value }

如果没有返回值的时候可以省了 () -> [type] {} 写法,直接 fn name () {} 即可:

ini 复制代码
fn set_flag() {
    let mut flag = false;
    flag = true;
}

Rustdoc

说到函数,我们就需要讲讲Rustdoc。Rust和其他语言一样提供了文档说明的工具链。

在javascript中类似jsDoc。

使用起来有点奇怪但也是够用,需要你使用///不像js那种/**/

rust 复制代码
/// Determine whether the first argument is divisible by the second argument.
///
/// If the second argument is zero, the result is false.
///
/// # Example
/// ```
/// assert!(is_divisible_by(42, 2));
/// ```
fn is_divisible_by(lhs: u32, rhs: u32) -> bool {
    if rhs == 0 {
        return false;  // Corner case, early return
    }
    lhs % rhs == 0     // The last expression in a block is the return value
}

如果你定义好之后在IDE上就可以看到如下效果:

当然如你喜欢MD方式也可以这么定义

重载

重载这个在强制类型的语言里非常重要,决定你的函数能不能扩展取决定性因素。

每个函数都有一个单独的实现,取决两个因数

  1. 始终采用固定数量的参数。
  2. 始终采用单个参数类型集。
rust 复制代码
// 比如这里是第二种情况。
fn add(x: i32, y: i32) -> i32 {
    x + y
}

fn add(x: f64, y: f64) -> f64 {
    x + y
}

"

注意的是rust中函数体是不支持默认值参数的。

Rust团队给出的理由是

  1. 所有调用点都有相同数量的参数。你定义函数的时候每个参数都应该有意义。
  2. 宏有时被用作替代。

但是有了泛型重载的工作量也可以适当的较少。比如这样

rust 复制代码
fn pick_one<T>(a: T, b: T) -> T {
    if std::process::id() % 2 == 0 { a } else { b }
}

fn main() {
    println!("coin toss: {}", pick_one("heads", "tails"));
    println!("cash prize: {}", pick_one(500, 1000));
}

微信搜索梦兽编程公众号

参考资料

1

google.github.io/comprehensi...: google.github.io/comprehensi...

本文使用 markdown.com.cn 排版

相关推荐
Victor35611 小时前
https://editor.csdn.net/md/?articleId=139321571&spm=1011.2415.3001.9698
后端
Victor35611 小时前
Hibernate(89)如何在压力测试中使用Hibernate?
后端
灰子学技术12 小时前
go response.Body.close()导致连接异常处理
开发语言·后端·golang
Gogo81613 小时前
BigInt 与 Number 的爱恨情仇,为何大佬都劝你“能用 Number 就别用 BigInt”?
后端
fuquxiaoguang13 小时前
深入浅出:使用MDC构建SpringBoot全链路请求追踪系统
java·spring boot·后端·调用链分析
毕设源码_廖学姐14 小时前
计算机毕业设计springboot招聘系统网站 基于SpringBoot的在线人才对接平台 SpringBoot驱动的智能求职与招聘服务网
spring boot·后端·课程设计
野犬寒鸦15 小时前
从零起步学习并发编程 || 第六章:ReentrantLock与synchronized 的辨析及运用
java·服务器·数据库·后端·学习·算法
逍遥德16 小时前
如何学编程之01.理论篇.如何通过阅读代码来提高自己的编程能力?
前端·后端·程序人生·重构·软件构建·代码规范
MX_935917 小时前
Spring的bean工厂后处理器和Bean后处理器
java·后端·spring
程序员泠零澪回家种桔子18 小时前
Spring AI框架全方位详解
java·人工智能·后端·spring·ai·架构