前言
无。
环境搭建
懒得开虚拟机了,所以不打算弄远程开发,先去官网网站搞一个Windows的开发环境,后续再弄Linux的部署环境,安装完成后输入版本查询命令验证安装:
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:
fn main() {
println!("Hello WOrld!");
}
函数调用加了个感叹号,有点稀奇,再编译成可执行文件:
rustc .\index.rs
看到生成了一个exe可执行文件和一个pdb文件,运行exe文件即可输出Hello World:
PS D:\Code\Rust\study> .\index.exe
Hello WOrld!
看了下文档,println还支持参数代入和数字前缀填充等等功能:
fn main() {
println!("Hello World, No.{n:>0wid$} {0}!", "Twings", n=1, wid=6);
}
得到结果:
PS D:\Code\Rust\study> .\index.exe
Hello World, No.000001 Twings!
结构体(类)
Rust的类即结构体:
#[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)]可以打印结构体方便查看内容,打印结果:
PS D:\Code\Rust\study> .\index.exe
Person { name: "Pite", age: 28, birthday: "20770707", power: 5000 }
也可以用更简洁一点的实例化方式:
let pite = Person{
name: "Pite",
age: 28,
birthday: "20770707",
power: 5000
};
也可以通过定义函数的方式,给每种结构体自定义自己的打印方式:
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);
}
输出结果:
PS D:\Code\Rust\study> .\index.exe
Pite, age: 28, birthday: 20770707 , power: 5000
既然有类(结构体),那么自然也会有接口和类方法,Rust中的接口就是trait特质,可以在特质中定义抽象接口:
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:
模块内定义的特质,模块外调用其方法是要先使用use引入
Display打印结构体时,除了该结构体本身,结构体中的结构体也要实现Display方法
乱七八糟的泛型和生命周期定义
变量
类型、枚举和生命周期先略过,等要用到再说。
变量以let关键字进行定义,虽然是强类型语言,但是编译时编译器会自行推断一些变量类型:
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);
}
输出:
PS D:\Code\Rust\study> .\index.exe
An string: "abc"
A integer: 2333
A integer too: 2333
在rust中,变量默认是不可修改的:
fn main() {
let a = 777;
a = 4396;
}
尝试修改变量就会在编译时报错,无法为一个不可变变量赋值两次:
error[E0384]: cannot assign twice to immutable variable `a`
此时就需要将其定义为可变变量:
fn main() {
let mut a = 777;
a = 4396;
}
这样就不会有问题。
流程控制
if条件判断
条件判断略过。
循环
循环语句用的是loop:
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);
}
结果:
PS D:\Code\Rust\study> .\index.exe
0x12
loop循环可以按标签分层,还可以中断循环的同时返回一个值。
还有while循环,略过。
for循环稍有不同:
fn main() {
for n in 1..=100 {
println!("0x{:x}", n);
}
}
用..=代替了其他语言下面的:
a=0;a<=100;a++
match模式匹配
类似其它语言的switch语句:
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),
}
}
}
除了匹配某个确定的值,还可以设置多个值、区间和默认。