Rust后端开发入门

前言

无。


环境搭建

懒得开虚拟机了,所以不打算弄远程开发,先去官网网站搞一个Windows的开发环境,后续再弄Linux的部署环境,安装完成后输入版本查询命令验证安装:

1
2
3
4
PS C:\Users\admin> rustup -V
rustup 1.27.1 (54dd3d00f 2024-04-24)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.81.0 (eeb90cda1 2024-09-04)`

Hello World

官方文档找到Hello World的栗子,先简单学习一手。

感觉文档问题很大,不先讲函数等等语法,先讲数组元组又讲它们怎么作为函数参数和返回值来用,返回语句还没有return,刚看到的时候懵了一下。

首先是新建一个Rust代码文件index.rs,然后写上hello world:

1
2
3
fn main() {
println!("Hello WOrld!");
}

函数调用加了个感叹号,有点稀奇,再编译成可执行文件:

1
rustc .\index.rs

看到生成了一个exe可执行文件和一个pdb文件,运行exe文件即可输出Hello World:

1
2
PS D:\Code\Rust\study> .\index.exe
Hello WOrld!

看了下文档,println还支持参数代入和数字前缀填充等等功能:

1
2
3
fn main() {
println!("Hello World, No.{n:>0wid$} {0}!", "Twings", n=1, wid=6);
}

得到结果:

1
2
PS D:\Code\Rust\study> .\index.exe
Hello World, No.000001 Twings!

结构体(类)

Rust的类即结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#[derive(Debug)]
struct Person<'a>{
name: &'a str,
age: u8,
birthday: &'a str,
power: i32
}

fn main() {
let name = "Pite";
let age = 28;
let birthday = "20770707";
let power = 5000;
let pite = Person{name, age, birthday, power};
println!("{:?}", pite);
}

通过配置#[derive(Debug)]可以打印结构体方便查看内容,打印结果:

1
2
PS D:\Code\Rust\study> .\index.exe     
Person { name: "Pite", age: 28, birthday: "20770707", power: 5000 }

也可以用更简洁一点的实例化方式:

1
2
3
4
5
6
let pite = Person{
name: "Pite",
age: 28,
birthday: "20770707",
power: 5000
};

也可以通过定义函数的方式,给每种结构体自定义自己的打印方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
use std::fmt::{self, Formatter, Display};

struct Person<'a>{
name: &'a str,
age: u8,
birthday: &'a str,
power: i32
}

impl<'a> Display for Person<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}, age: {}, birthday: {}, power: {}",
self.name, self.age, self.birthday, self.power)
}
}

fn main() {
let name = "Pite";
let age = 28;
let birthday = "20770707";
let power = 5000;
let pite = Person{name, age, birthday, power};
println!("{}", pite);
}

输出结果:

1
2
PS D:\Code\Rust\study> .\index.exe
Pite, age: 28, birthday: 20770707 , power: 5000

既然有类(结构体),那么自然也会有接口和类方法,Rust中的接口就是trait特质,可以在特质中定义抽象接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
mod my_mod{
use std::fmt::{self, Formatter, Display};

pub trait Animal<'a, T> {
fn new(name: &'a str, age: u8, birthday: &'a str, power: i32, secret: T) -> Self;
fn get_name(&self) -> &'a str;
fn get_age(&self) -> u8;
}

pub struct Person<'a, T> {
name: &'a str,
age: u8,
birthday: &'a str,
power: i32,
secret: T
}

impl<'a, T> Person<'a, T> {
pub fn get_secret(&self) -> &T {
&self.secret
}
}

impl<'a, T> Animal<'a, T> for Person<'a, T> {
fn new(name: &'a str, age: u8, birthday: &'a str, power: i32, secret: T) -> Self {
Person{
name: name,
age: age,
birthday: birthday,
power: power,
secret: secret
}
}
fn get_name(&self) -> &'a str {
self.name
}
fn get_age(&self) -> u8 {
self.age
}
}

pub struct Secret<'a> {
pub content: &'a str
}

impl<'a, T: Display> Display for Person<'a, T> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}, age: {}, birthday: {}, power: {}, secret: {}",
self.name, self.age, self.birthday, self.power, self.secret)
}
}

impl<'a> Display for Secret<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "/*{}*/",
self.content)
}
}
}

use my_mod::Animal;

fn main() {
let pite: my_mod::Person<my_mod::Secret> = my_mod::Animal::new(
"Pite",
28,
"20770707",
5000,
my_mod::Secret{content: "No way!"}
);
println!("{}", pite);
println!("{}, {}, {}", pite.get_name(), pite.get_age(), pite.get_secret());
}

trait中定义的方法与trait本身具有相同的可见性配置(pub)。

搞了个模块+泛型+结构体+特质+方法的代码,一直debug,搞得头都大了,几个主要的bug:

  1. 模块内定义的特质,模块外调用其方法是要先使用use引入

  2. Display打印结构体时,除了该结构体本身,结构体中的结构体也要实现Display方法

  3. 乱七八糟的泛型和生命周期定义

变量

类型、枚举和生命周期先略过,等要用到再说。

变量以let关键字进行定义,虽然是强类型语言,但是编译时编译器会自行推断一些变量类型:

1
2
3
4
5
6
7
8
fn main() {
let a = "abc";
let b = 2333;
let c = 2333.333;
println!("An string: {:?}", a);
println!("A integer: {:?}", b);
println!("A integer too: {:?}", c as u32);
}

输出:

1
2
3
4
PS D:\Code\Rust\study> .\index.exe
An string: "abc"
A integer: 2333
A integer too: 2333

在rust中,变量默认是不可修改的:

1
2
3
4
fn main() {
let a = 777;
a = 4396;
}

尝试修改变量就会在编译时报错,无法为一个不可变变量赋值两次:

1
error[E0384]: cannot assign twice to immutable variable `a`

此时就需要将其定义为可变变量:

1
2
3
4
fn main() {
let mut a = 777;
a = 4396;
}

这样就不会有问题。

流程控制

if条件判断

条件判断略过。

循环

循环语句用的是loop:

1
2
3
4
5
6
7
8
9
10
11
fn main() {
let x = 9u32;
let mut y = 0u32;
let res = loop {
y += 1;
if x * y == 81 {
break x + y;
}
};
println!("0x{:x}", res);
}

结果:

1
2
PS D:\Code\Rust\study> .\index.exe
0x12

loop循环可以按标签分层,还可以中断循环的同时返回一个值。

还有while循环,略过。

for循环稍有不同:

1
2
3
4
5
fn main() {
for n in 1..=100 {
println!("0x{:x}", n);
}
}

用..=代替了其他语言下面的:

1
a=0;a<=100;a++

match模式匹配

类似其它语言的switch语句:

1
2
3
4
5
6
7
8
9
10
fn main() {
for n in 1..=100 {
match n {
1 => println!("One!!!0x{:x}", n),
2 | 4 | 6 | 8 => println!("Two!!!0x{:x}", n),
20..=30 => println!("Three!!!0x{:x}", n),
_ => println!("None!!!0x{:x}", n),
}
}
}

除了匹配某个确定的值,还可以设置多个值、区间和默认。


官网网址

官方文档


Rust后端开发入门
http://yoursite.com/2024/10/09/Rust后端开发入门/
作者
Aluvion
发布于
2024年10月9日
许可协议