rust学习笔记1.基础语法(代码片段)

归止于飞 归止于飞     2023-02-15     774

关键词:

文章目录

Rust的基本语法

0、猜字游戏

完成以下代码的运行,也就代表着基本了解Rust代码的运行逻辑,更代表自己的Rust开发环境已经正常。

use rand::Rng;
use std::cmp::Ordering;
use std::io;

fn main() 
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1..=100);

    println!("The secret number is:secret_number");

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: guess");

    match guess.cmp(&secret_number) 
        Ordering::Less => println!("Too small"),
        Ordering::Greater=>println!("Too big"),
        Ordering::Equal=>println!("You win"),
    

1、Cargo是什么

Cargo 是 Rust 的构建系统和包管理器。

2、输出字符串

函数println!和print!,ln会输出字符串最后的换行符。

注意,Rust的占位符为

3、基础语法

赋值

Rust是一门强类型语言,但是为了高并发安全所做的设计,存在可变与不可变变量。

使用let 进行赋值,加上关键字mut后成为可变变量

重影

重影与可变变量的赋值不是一个概念,重影是指用同一个名字重新代表另一个变量实体,其类型、可变属性和值都可以变化。但可变变量赋值仅能发生值的变化。

4、Rust的数据类型

  • 整数型
  • 浮点型
  • 布尔型
  • 字符型
  • 复合类型 注意()与[]的区别

()包含不同类型,[]包含相同类型

5、Rust的注释

一般是//与/*……*/

为说明文档注释时使用///

6、Rust的函数

fn <函数名> ( <参数> ) <函数体>

Rust不在乎何处定义函数,只需在某个地方定义它们即可。

函数体的语句和表达式

注意Rust可以使用返回值进行定义,如下图这个例子:

fn main() 
    let x = 5;

    let y = 
        let x = 3;
        x + 1
    ;

    println!("x 的值为 : ", x);
    println!("y 的值为 : ", y);

函数返回值

fn add(a: i32, b: i32) -> i32 
  return a + b;

7、条件语句

if-else语句,条件必须为bool类型

8、循环语句

  • while循环
  • for循环
  • loop循环

loop 循环可以通过 break 关键字类似于 return 一样使整个循环退出并给予外部一个返回值。这是一个十分巧妙的设计,因为 loop 这样的循环常被用来当作查找工具使用,如果找到了某个东西当然要将这个结果交出去。

9、所有权

所有权是Rust特有的资源管理机制,与别的语言的非常不同,需要注意。

Rust的所有权

变量范围,与相关

内存的分配


  char *s = strdup("runoob");
  free(s); *// 释放 s 资源*

实际上Rust没有什么确切的内存释放,而是依靠着编译器自带的内存释放,这里就使用到Rust的特定的功能,即所有权的问题。

变量与数据交互方式

移动

移动后会销毁签名那个变量,防止对值得二次销毁

克隆

多复制一份数据在堆里

垂悬引用

类似C++的空指针,在Rust里就是所引用的值已经被销毁。

10、切片

对数组或字符串数组进行的切片,即进行截取。

11、结构体

记住格式即可,与C/C++类似,但是Rust的结构体常常在面向对象里使用。

结构体类名 
    字段名 : 字段值,
    ...

12、枚举类

Rust的枚举类较为复杂。

enum Book 
    Papery(u32),
    Electronic(String),


let book = Book::Papery(1001);
let ebook = Book::Electronic(String::from("url://..."));

match语法

类似于switch语法,但是有相应改进。

match 枚举类实例 
    分类1 => 返回值表达式,
    分类2 => 返回值表达式,
    ...

Option枚举类

Option 是 Rust 标准库中的枚举类,这个类用于填补 Rust 不支持 null 引用的空白。

if let语法

只是区分两种情况的match语法糖

if let 匹配值 = 源变量 
    语句块

13、生命周期

生命周期是与所有权同样重要的资源管理机制

生命周期注释

生命周期注释是描述生命周期的发布方法

&i32        // 常规引用
&'a i32     // 含有生命周期注释的引用
&'a mut i32 // 可变型含有生命周期注释的引用

函数的生命周期参数

函数的生命周期声明是函数的入参和返回值的一种生命周期约定和限制

结构体定义的生命周期声明

当我们定义的struct的里面有对象引用的时候,我们需要在struct的模板参数中增加生命周期声明。

以下引用情况不需要使用生命周期

  • 函数的每个参数将会赋予各自的生命周期。
  • 如果输入参数只有一个生命周期参数,那个这个生命周期参数将会被赋予所有输入值。
  • 在struct的impl语句中,如果有多个输入参数,但是输入参数中有**&self或者&mut self**,那么self的生命周期将会被赋予所有的书参数。

泛型,特性,生命周期协同使用

use std::fmt::Display;

fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str
    where T: Display

    println!("Announcement! ", ann);
    if x.len() > y.len() 
        x
     else 
        y
    

14、Rust组织管理

箱 crate

它是树状结构,存在于包中。

包 package

工程的实质就是一个包,包必须由Cargo.toml管理

模块Module

Rust的组织单位是模块。

类似于Java的类,JavaScript组织模块方式为function。

mod nation 
    mod government 
        fn govern() 
    
    mod congress 
        fn legislate() 
    
    mod court 
        fn judicial() 
    

在文件系统中,目录结构往往以斜杠在路径字符串中表示对象的位置,Rust 中的路径分隔符是 ::

路径分为绝对路径和相对路径。绝对路径从 crate 关键字开始描述。相对路径从 self 或 super 关键字或一个标识符开始描述。

访问权限

Rust的访问权限:公共与私有。

难以发现的模块

use关键字

使用use关键字可以将模块标识符引用当前作用域。

引用标准库

15、错误处理

Rust有一套独特的错误处理机制

不可恢复错误

panic!

可恢复错误

use std::fs::File;

fn main() 
    let f = File::open("hello.txt");
    match f 
        Ok(file) => 
            println!("File opened successfully.");
        ,
        Err(err) => 
            println!("Failed to open the file.");
        
    

如果想使一个可恢复错误按不可恢复错误处理,Result 类提供了两个办法:unwrap() 和 expect(message: &str) :

kind方法

kind函数可以获取Result的Err类型。

16、泛型与特性

泛型是每一个编程语言必不可少的一部分。

C++使用模板来实现。

在函数中定义泛型

fn max(array: &[i32]) -> i32 
    let mut max_index = 0;
    let mut i = 1;
    while i < array.len() 
        if array[i] > array[max_index] 
            max_index = i;
        
        i += 1;
    
    array[max_index]


fn main() 
    let a = [2, 4, 6, 3, 1];
    println!("max = ", max(&a));

结构体与枚举类的泛型

结构体与枚举类都可以定义方法,那么方法也应该实现泛型的机制,否则泛型的类将无法被有效的方法操作。

特性

特性的概念接近于Java中的接口,以及C++中的虚函数。

trait Descriptive 
    fn describe(&self) -> String;

Rust 同一个类可以实现多个特性,每个 impl 块只能实现一个。

17、面向对象

封装

总之,使用struct定义成员变量,使用类定义成员方法。

在Rust中可以用模块实现最外层的封装,每一个Rust都可以作为一个模块,模块内的天涯不属于可以通过pub对外明示。

“类”是面向对象编程常常用到的概念。“类”封装的是数据

在 Rust 中,我们可以使用结构体或枚举类来实现类的功能:

pub struct ClassName 
    pub field: Type,


pub impl ClassName 
    fn some_method(&self) 
        // 方法函数体
    


pub enum EnumName 
    A,
    B,


pub impl EnumName 
    fn some_method(&self) 

    

继承

Rust 没有提供跟继承有关的语法糖,也没有官方的继承手段(完全等同于 Java 中的类的继承),但灵活的语法依然可以实现相关的功能。

18、文件与IO

接受命令行参数

环境参数需要std::env取出

fn main() 
    let args = std::env::args();
    println!(":?", args);

文件读取

读取文本文件:

use std::fs;

fn main() 
    let text = fs::read_to_string("D:\\\\text.txt").unwrap();
    println!("", text);

读取二进制文件:

use std::fs;

fn main() 
    let content = fs::read("D:\\\\text.txt").unwrap();
    println!(":?", content);

文件流读取方式:

use std::io::prelude::*;
use std::fs;

fn main() 
    let mut buffer = [0u8; 5];
    let mut file = fs::File::open("D:\\\\text.txt").unwrap();
    file.read(&mut buffer).unwrap();
    println!(":?", buffer);
    file.read(&mut buffer).unwrap();
    println!(":?", buffer);

std::fs 模块中的 File 类是描述文件的类,可以用于打开文件,再打开文件之后,我们可以使用 File 的 read 方法按流读取文件的下面一些字节到缓冲区(缓冲区是一个 u8 数组),读取的字节数等于缓冲区的长度。

文件写入

一次性写入:

use std::fs;

fn main() 
    fs::write("D:\\\\text.txt", "FROM RUST PROGRAM")
        .unwrap();

流写入:

use std::io::prelude::*;
use std::fs::File;

fn main() 
    let mut file = File::create("D:\\\\text.txt").unwrap();
    file.write(b"FROM RUST PROGRAM").unwrap();

19、集合与字符串

集合是数据结构中最普遍的数据存放形式。

向量

向量(Vector)是一个存放多值的单数据结构,该结构将相同类型的值线性的存放在内存中。

向量是线性表,在 Rust 中的表示是 Vec。

向量的使用方式类似于列表(List),我们可以通过这种方式创建指定类型的向量:

let vector: Vec<i32> = Vec::new(); // 创建类型为 i32 的空向量
let vector = vec![1, 2, 4, 8];     // 通过数组创建向量

常用方法:

  • append将一个向量拼接到另一个向量尾部

  • get方法取出向量的值(同样可以使用数组表示法)

字符串

常用函数:

let mut s = String::from("run");
s.push_str("oob"); // 追加字符串切片
s.push('!');       // 追加字符

let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2;

let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = s1 + "-" + &s2 + "-" + &s3;

//求字符长度
let s = "hello";
let len = s.len();
// 因为中文每个字符长3字节。统计字符数量应该先统计字符集合
let s = "hello你好";
let len = s.chars().count();

//遍历字符串
fn main() 
    let s = String::from("hello中文");
    for c in s.chars() 
        println!("", c);
    


//从字符串中取出单个字符
fn main() 
    let s = String::from("EN中文");
    let a = s.chars().nth(2);
    println!(":?", a);

//注意,nth不能用在遍历中

//注意截取字符串时必须特别注意UTF-8字符,以下程序会报错
fn main() 
    let s = String::from("EN中文");
    let sub = &s[0..3];
    println!("", sub);

映射

映射表(Map)在其他语言中广泛存在。其中应用最普遍的就是键值散列映射表(Hash Map)。

use std::collections::HashMap;

fn main() 
    let mut map = HashMap::new();

    map.insert("color", "red");
    map.insert("size", "10 m^2");

    println!("", map.get("color").unwrap());

python学习笔记(代码片段)

...配5.其它5.1.StringIOBytesIO5.2.序列化5.2.1pickle5.2.2.JSON供个人学习笔记回顾时使用.1.异常没啥说的,语法换下而已.下文只会记录一下和JS语法不同的地方:基础语法:try...except...finally...一.可以expect多个异常,例 查看详情

kotlin基础语法学习笔记(代码片段)

Kotlin简介Kotlin是一门与Swift类似的静态类型JVM语言,由JetBrains设计开发并开源。与Java相比,Kotlin的语法更简洁、更具表达性,而且提供了更多的特性,比如,高阶函数、操作符重载、字符串模板。它与Java高度... 查看详情

c++基础学习笔记(代码片段)

一、简介C++是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。二、基本语法1、注释#include<iostream>usingnamespacestd;intmain()/*这是注释*//*C++注释也可以*跨行*... 查看详情

吴恩达深度学习笔记(代码片段)

...eLU函数(PReLU)ELU(ExponentialLinearUnits)函数总结前言学习的第二天一、一些基础的numpy语法importnumpyasnpa=np 查看详情

javascript学完js基础,顺便把js高级语法学了(尚硅谷视频学习笔记)(代码片段)

文章目录【1】基本总结深入一、什么是数据1、数据类型基本(值)类型对象(引用)类型2、判断相关问题二、什么是内存1、什么是数据2、什么是内存?3、什么是变量4、内存、数据、变量三者之间的关系相... 查看详情

go语言学习笔记—基础—基本语法—类型相关:类型定义与类型别名(代码片段)

类型别名主要用于go代码升级、迁移中,类型的兼容性问题。这解决了代码重构中最麻烦的类型名变更问题。1.类型定义与类型别名类型定义写法:typeTypeDefType栗子:typebyteuint8typeruneint32类型别名写法:typeTypeAlias... 查看详情

react学习笔记基础(代码片段)

文章目录jsx语法组件this.propsthis.refs.refNamethis.state事件监听生命周期constructor(props,context)componentWillMount()render()componentDidMount()componentWillReceiveProps(nextProps)shouldComponentUpdate(nextProps,nex 查看详情

c++基础学习笔记c++语法之引用(代码片段)

文章目录引用引用概念引用的使用方式:引用特性常引用使用场景传值、传引用效率比较引用和指针的区别引用引用概念引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空... 查看详情

rust学习笔记-变量和类型(代码片段)

变量通常一门的语言的变量是没有啥可以说道的,无法就是变量命名规则:以字母、下划线和数字组成,并且数字不能开头,没啥好说的。但rust的变量奇怪的地方是,变量不可变譬如这样一个简单到不能再简... 查看详情

c++学习:1基础语法(代码片段)

C++发展史C++03只是修改了一些BUGC++11:majorC++17:major目录一、基础语法A1、cin、cout2、函数重载(Overload)3、默认参数4、extern"C"C和C++混合开发二、基础语法B5、内联函数( 查看详情

java后端开发工程师学习笔记狂神说java笔记(代码片段)

目录面试题库阶段一:Java基础1.计算机基础2.Java入门学习3.java基础语法4.流程控制5.方法6.数组7.面向对象编程8.异常9.常用类10.集合框架11.IO流12.多线程13.GUI编程14.网络编程15.注解和反射16.JUC编程17.JVM探究阶段二:前端基础... 查看详情

机器学习基础教程笔记---机器学习概述(代码片段)

目录机器学习概述1.1人工智能概述1.1.1机器学习与人工智能、深度学习1.1.2机器学习、深度学习能做些什么1.1.3人工智能阶段课程安排1.2什么是机器学习1.2.1定义1.2.2解释1.2.3数据集构成1.3机器学习算法分类学习目标分析1.2中的例子... 查看详情

c#学习笔记(18)操作sqlserver中(代码片段)

C#学习笔记(18)操作SQLServer中数据库基础操作SQL语法可以参考菜鸟教程或者微软官方的SQL示例注意SQL不区分大小写查1.基础查询--最基础的查询语句,select*fromtable_nameselect*fromstudentTable2.条件查询--条件查询select*fromtable... 查看详情

go语言学习笔记—基础—基本语法—常量与变量—常量变量的声明:多个变量的初始化声明与赋值(代码片段)

1.声明的方式多个变量声明与赋值//为类型相同的多个变量赋值varvname1,vname2,vname3typevname1,vname2,vname3=v1,v2,v3并行赋值varvname1,vname2,vname3type=v1,v2,v3自动类型推断//和python很像,不需要显示声明类型,自动推断varvname1,vname2... 查看详情

go学习golang底层学习笔记(代码片段)

1.1.1.Go编译词法与语法分析意义:解析源代码文件,将文件中字符串序列转换成Token序列把执行词法分析的程序称为词法解析器(lexer)语法解析的结果就是抽象语法树(AST)每个AST都对应一个单独的Go语言文件,这个抽象语法树中包括当前... 查看详情

黄佳《零基础学机器学习》chap1笔记(代码片段)

黄佳《零基础学机器学习》chap1笔记这本书实在是让我眼前一亮!!!感觉写的真的太棒了!文章目录黄佳《零基础学机器学习》chap1笔记第1课机器学习快速上手路径——唯有实战1.1机器学习族谱1.2云环境入门实... 查看详情

go语言学习笔记—基础—基本语法—常量与变量—变量的生命周期:栈(stack)(代码片段)

栈是一种拥有特殊规则的线性表。1.概念栈的操作(入栈和出栈)和栈元素扩展栈只允许向线性表的一端放入数据,之后在同一端取出数据。按照后进先出(或先进后出)的顺序向栈中放入元素的过程叫入栈&#x... 查看详情

mysql基础学习笔记(代码片段)

本文主要分为四部分来写;是学习mysql数据库基础的学习笔记1、MYSQL基础(1到6)2、性能优化(7-11)3、MYSQL锁机制(12-14)4、主从复制这里前面几章主要是mysql的基础实际操作我基础写完之后单独写一... 查看详情