• 注册
  • 后端开发博客 后端开发博客 关注:0 内容:1997

    【最少必要知识】Rust极速入门,听说Rust可以写前端,FEer来入门吧

  • 查看作者
  • 打赏作者
  • 当前位置: 职业司 > 后端开发 > 后端开发博客 > 正文
    • 后端开发博客
    • 本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!

      Rust安装(Mac)

      curl --proto '=https' --tlsv1.2 -sSf  链接 | sh
      复制代码

      安装完测试下

      cargo -V
      cargo 1.53.0 (4369396ce 2021-04-27)
      复制代码

      创建项目

      cargo new rust-miao
      复制代码

      创建目录如下:

         |--Cargo.toml
      |--target # 编译目录,忽略
      |--Cargo.lock
      |--.gitignore
      |--.git # git目录,忽略
      |--src
      |   |--main.rs
      复制代码

      运行看看

      cargo run
      Compiling rust-miao v0.1.0 (/Users/woojufon/Desktop/rust-miao)
      Finished dev [unoptimized + debuginfo] target(s) in 0.81s
      Running `target/debug/rust-miao`
      Hello, world!
      复制代码

      改下main.rs

      fn main() {
      println!("Hello, miao!");
      }
      复制代码

      再执行

      cargo run
      Finished dev [unoptimized + debuginfo] target(s) in 0.00s
      Running `target/debug/rust-miao`
      Hello, miao!
      复制代码

      建议使用vscode并安装Rust and Friends插件,提示会比较友好

      开始

      占位符{}

      fn main() {
      let i = "huamiao";
      println!("I'm {}", i);
      }
      复制代码

      变量

      Rust 是强类型语言,但具有自动判断变量类型的能力,类似前端同学用ts,又不爱写类型。

      let a = 123;
      // 以下三行代码都错
      a = "abc";
      a = 4.56;
      a = 456;
      复制代码

      初始化变量会自动给定类型,1、2行错,3行可变变量rust不这么写,要这么写

      let mut a = 123;
      a = 456;
      复制代码

      mutable=mut,可变

      别问我为什么,问了阿婆主就自尽,不信你试试

      但是可以被重新定义:

      fn main() {
      let i = "huamiao";
      println!("I'm {}", i);
      let i = "miaomiao";
      println!("I'm {}", i);
      }
      复制代码
      cargo run
      Compiling rust-miao v0.1.0 (/Users/woojufon/Desktop/rust-miao)
      Finished dev [unoptimized + debuginfo] target(s) in 0.23s
      Running `target/debug/rust-miao`
      I'm huamiao
      I'm miaomiao
      复制代码

      字符串需要用双引号,单引号只能定义单个字符,语句要;结尾

      类型

      整型
      位长度 有符号 无符号
      8-bit i8 u8
      16-bit i16 u16
      32-bit i32 u32
      64-bit i64 u64
      128-bit i128 u128
      arch isize usize

      整数的表述方法

      进制
      十进制 98_222
      十六进制 0xff
      八进制 0o77
      二进制 0b1111_0000
      字节(只能表示 u8 型) b'A'
      浮点数

      类型声明很像ts不

      fn main() {
      let x = 2.0; // f64
      let y: f32 = 3.0; // f32
      }
      复制代码
      数学运算
      fn main() {
      let sum = 5 + 10; // 加
      let difference = 95.5 - 4.3; // 减
      let product = 4 * 30; // 乘
      let quotient = 56.7 / 32.2; // 除
      let remainder = 43 % 5; // 求余
      }
      复制代码

      Rust 不支持  ++  和 --

      布尔型,true/false
      字符型

      字符型用 char 表示,4个字节,Rust 中字符串和字符都必须使用 UTF-8 编码。

      复合类型

      元组用一对 ( ) 包括的一组数据,可以包含不同种类的数据:

      let tup: (i32, f64, u8) = (500, 6.4, 1);
      // tup.0 等于 500
      // tup.1 等于 6.4
      // tup.2 等于 1
      let (x, y, z) = tup;
      // y 等于 6.4
      复制代码

      数组用一对 [ ] 包括的同类型数据。

      let a = [1, 2, 3, 4, 5];
      // a 是一个长度为 5 的整型数组
      let b = ["January", "February", "March"];
      // b 是一个长度为 3 的字符串数组
      let c: [i32; 5] = [1, 2, 3, 4, 5];
      // c 是一个长度为 5 的 i32 数组
      let d = [3; 5];
      // 等同于 let d = [3, 3, 3, 3, 3];
      let first = a[0];
      let second = a[1];
      // 数组访问
      a[0] = 123; // 错误:数组 a 不可变
      let mut a = [1, 2, 3];
      a[0] = 4; // 正确
      复制代码

      注释

      // 这是第一种注释方式
      /* 这是第二种注释方式 */
      /*
      * 多行注释
      * 多行注释
      * 多行注释
      */
      复制代码

      文档注释

      vscode引用方法的时候放上面会提示

      /// Adds one to the number given.
      ///
      /// # Examples
      ///
      /// ```
      /// let x = add(1, 2);
      ///
      /// ```
      复制代码

      函数

      fn <函数名> ( <参数> ) <函数体>
      复制代码

      函数名称的命名风格是小写字母以下划线分割

      fn main() {
      println!("Hello, world!");
      another_function();
      }
      fn another_function() {
      println!("Hello, miao!");
      }
      复制代码

      main 函数之后定义了another_function也是正常的,rust no care

      参数

      定义函数如果需要具备参数必须声明参数名称和类型

      fn main() {
      another_function(5, 6);
      }
      fn another_function(x: i32, y: i32) {
      println!("x 的值为 : {}", x);
      println!("y 的值为 : {}", y);
      }
      复制代码

      语句块

      fn main() {
      let x = 5;
      let y = {
      let x = 3;
      x + 1
      };
      println!("x 的值为 : {}", x);
      println!("y 的值为 : {}", y);
      }
      复制代码

      嵌套函数

      fn main() {
      fn five() -> i32 {
      5
      }
      println!("five() 的值为: {}", five());
      }
      复制代码

      -> i32指定返回值类型

      函数体表达式(嵌套函数)并不能等同于函数体,它不能使用 return 关键字

      Rust 不支持自动返回值类型判断,需要明确声明函数返回值的类型才可以指定返回值,return 后面不能有返回值表达式,如:a+b

      条件语句

      条件不需要(),也可以有,单条语句也要{}

      fn main() {
      let a = 12;
      let b;
      if a > 0 {
      b = 1;
      }
      else if a < 0 {
      b = -1;
      }
      else {
      b = 0;
      }
      println!("b is {}", b);
      }
      复制代码

      不像js会自动转换类型:

      fn main() {
      let number = 3;
      if number {   // 报错,expected `bool`, found integerrustc(E0308)
      println!("Yes");
      }
      }
      复制代码

      三元

      fn main() {
      let a = 3;
      let number = if a > 0 { 1 } else { -1 };
      println!("number 为 {}", number);
      }
      复制代码

      循环语句

      fn main() {
      let mut number = 1;
      while number != 4 {
      println!("{}", number);
      number += 1;
      }
      println!("EXIT");
      }
      复制代码

      for

      fn main() {
      let a = [10, 20, 30, 40, 50];
      for i in a.iter() {
      println!("值为 : {}", i);
      }
      }
      复制代码

      for in

      fn main() {
      let a = [10, 20, 30, 40, 50];
      for i in 0..5 {
      println!("a[{}] = {}", i, a[i]);
      }
      }
      复制代码

      loop无限循环

      fn main() {
      let s = ['R', 'U', 'N', 'O', 'O', 'B'];
      let mut i = 0;
      loop {
      let ch = s[i];
      if ch == 'O' {
      break;
      }
      println!("\'{}\'", ch);
      i += 1;
      }
      }
      复制代码

      break中断循环,可以返回值

      fn main() {
      let s = ['R', 'U', 'N', 'O', 'O', 'B'];
      let mut i = 0;
      let location = loop {
      let ch = s[i];
      if ch == 'O' {
      break i;
      }
      i += 1;
      };
      println!(" \'O\' 的索引为 {}", location);
      }
      复制代码

      常见错误/异常

      遇到这个再执行一次cargo run即可

      cargo run
      Compiling rust-miao v0.1.0 (/Users/woojufon/Desktop/rust-miao)
      Finished dev [unoptimized + debuginfo] target(s) in 0.44s
      Running `target/debug/rust-miao`
      zsh: killed     cargo run
      复制代码

      所有权,可以不管这个概念

      • 内存释放:在变量范围结束的时候,Rust 编译器自动添加了调用释放资源函数
      {
      // 在声明以前,变量 s 无效
      let s = "miao";
      // 这里是变量 s 的可用范围
      }
      // 变量范围已经结束,变量 s 无效,释放内存
      复制代码
      • 移动
      let s1 = String::from("hello");
      let s2 = s1;
      println!("{}, world!", s1); // 错误!s1 已经失效
      复制代码
      • 克隆
      fn main() {
      let s1 = String::from("hello");
      let s2 = s1.clone();
      println!("s1 = {}, s2 = {}", s1, s2);
      }
      复制代码
      • 如果将变量当作参数传入函数,那么它和移动的效果是一样的。
      fn main() {
      let s = String::from("hello");
      // s 被声明有效
      takes_ownership(s);
      // s 的值被当作参数传入函数
      // 所以可以当作 s 已经被移动,从这里开始已经无效
      let x = 5;
      // x 被声明有效
      makes_copy(x);
      // x 的值被当作参数传入函数
      // 但 x 是基本类型,依然有效
      // 在这里依然可以使用 x 却不能使用 s
      } // 函数结束, x 无效, 然后是 s. 但 s 已被移动, 所以不用被释放
      fn takes_ownership(some_string: String) {
      // 一个 String 参数 some_string 传入,有效
      println!("{}", some_string);
      } // 函数结束, 参数 some_string 在这里释放
      fn makes_copy(some_integer: i32) {
      // 一个 i32 参数 some_integer 传入,有效
      println!("{}", some_integer);
      } // 函数结束, 参数 some_integer 是基本类型, 无需释放
      复制代码
      • 函数返回值
      fn main() {
      let s1 = gives_ownership();
      // gives_ownership 移动它的返回值到 s1
      let s2 = String::from("hello");
      // s2 被声明有效
      let s3 = takes_and_gives_back(s2);
      // s2 被当作参数移动, s3 获得返回值所有权
      } // s3 无效被释放, s2 被移动, s1 无效被释放.
      fn gives_ownership() -> String {
      let some_string = String::from("hello");
      // some_string 被声明有效
      return some_string;
      // some_string 被当作返回值移动出函数
      }
      fn takes_and_gives_back(a_string: String) -> String {
      // a_string 被声明有效
      a_string  // a_string 被当作返回值移出函数
      }
      复制代码

      被当作函数返回值的变量所有权将会被移动出函数并返回到调用函数的地方,而不会直接被无效释放。

      • 引用、租借

      变量引用

      fn main() {
      let s1 = String::from("hello");
      let s2 = &s1;
      println!("s1 is {}, s2 is {}", s1, s2);
      }
      // s1 is hello, s2 is hello
      复制代码

      函数引用

      fn main() {
      let s1 = String::from("hello");
      let len = calculate_length(&s1);
      println!("The length of '{}' is {}.", s1, len);
      }
      fn calculate_length(s: &String) -> usize {
      s.len()
      }
      // The length of 'hello' is 5.
      复制代码

      错误的栗子

      fn main() {
      let s1 = String::from("hello");
      let s2 = &s1;
      let s3 = s1;
      println!("{}", s2);
      }
      复制代码

      s2 租借的 s1 已经将所有权移动到 s3,所以 s2 将无法继续租借使用 s1 的所有权

      需要重新租借

      fn main() {
      let s1 = String::from("hello");
      let mut s2 = &s1;
      let s3 = s2;
      s2 = &s3; // 重新从 s3 租借所有权
      println!("{}", s2);
      }
      复制代码

      租借禁止修改

      fn main() {
      let s1 = String::from("run");
      let s2 = &s1;
      println!("{}", s2);
      s2.push_str("oob"); // 错误,禁止修改租借的值
      println!("{}", s2);
      }
      复制代码

      要“授权”,如:

      fn main() {
      let mut s1 = String::from("run");
      // s1 是可变的
      let s2 = &mut s1;
      // s2 是可变的引用
      s2.push_str("oob");
      println!("{}", s2);
      }
      复制代码

      可变引用不允许多重引用,但不可变引用可以

      let mut s = String::from("hello");
      let r1 = &mut s;
      let r2 = &mut s;
      println!("{}, {}", r1, r2);
      复制代码

      这段程序不正确,因为多重可变引用了 s。

      切片

      fn main() {
      let s = String::from("broadcast");
      let part1 = &s[0..5];
      let part2 = &s[5..9];
      println!("{}={}+{}", s, part1, part2);
      }
      // broadcast=broad+cast
      复制代码

      除了字符串以外,其他一些线性数据结构也支持切片操作,例如数组:

      fn main() {
      let arr = [1, 3, 5, 7, 9];
      let part = &arr[0..3];
      for i in part.iter() {
      println!("{}", i);
      }
      }
      复制代码

      总结

      到此,Rust的最少必要知识就完了,相较于其他语言还是有比较大的区别的,有人说,面向对象没讲、日期没讲,这些我列在参考,必要知识就是让你能跑得起来,可以写基本的东西了,根据所需查阅更多知识插入到我们的代码中,阿婆主不会把“插件”或者说非必要知识列进来。

      参考

      • Rust 结构体
      • Rust 枚举类
      • Rust 组织管理
      • Rust 错误处理
      • Rust 泛型与特性
      • Rust 生命周期
      • Rust 文件与 IO
      • Rust 集合与字符串
      • Rust 面向对象
      • Rust 并发编程

      cargo补充

      • cargo clippy: 类似eslint,lint工具检查代码可以优化的地方
      • cargo fmt: 类似go fmt,代码格式化
      • cargo tree: 查看第三方库的版本和依赖关系
      • cargo bench: 运行benchmark(基准测试,性能测试)
      • cargo udeps(第三方): 检查项目中未使用的依赖

      另外 cargo build/run --release 使用 release 编译会比默认的 debug 编译性能提升 10 倍以上,但是 release 缺点是编译速度较慢,而且不会显示 panic backtrace 的具体行号

      请登录之后再进行评论

      登录

      手机阅读天地(APP)

      • 微信公众号
      • 微信小程序
      • 安卓APP
      手机浏览,惊喜多多
      匿名树洞,说我想说!
      问答悬赏,VIP可见!
      密码可见,回复可见!
      即时聊天、群聊互动!
      宠物孵化,赠送礼物!
      动态像框,专属头衔!
      挑战/抽奖,金币送不停!
      赶紧体会下,不会让你失望!
    • 实时动态
    • 签到
    • 做任务
    • 发表内容
    • 偏好设置
    • 到底部
    • 帖子间隔 侧栏位置:
    • 还没有账号?点这里立即注册