Struct 结构体 
基本使用 
自定义的数据类型,类似于 TS 的 interface。
rust
struct User {
    username: String,
    email: String,
    age: usize,
    active: bool,
} // 这里不需要分号
fn main() {
    // 如果需要 user1 里的字段可变,可以声明 let mut user1。那么里面的内容都是可以修改的。
    let user1 = User {
        username: String::from("王大锤"),
        email: String::from("xxxxxx@qq.com"),
        age: 13,
        active: true,
    };
    println!(
        "username: {}, email: {}, age: {}, active: {}",
        user1.username, user1.email, user1.age, user1.active
    );
    // username: 王大锤, email: xxxxxx@qq.com, age: 13, active: true
}Struct 也可以作为函数的返回值,字段名和字段值对应变量名相同时,可以简写,类似于 JS
rust
fn build_user(email:String, username: String) -> User {
    User {
        email,
        username,
        age:13,
        active:true
    }
}Struct 更新语法 
rust
fn main() {
    // 如果需要 user1 里的字段可变,可以声明 let mut user1,那么里面的内容都是可以修改的。
    let mut user1 = User {
        username: String::from("王大锤"),
        email: String::from("xxxxxx@qq.com"),
        age: 13,
        active: true,
    };
    let user2 = User {
        username: String::from("大锤giegie"),
        email: String::from("xxxx@163.com"),
        ..user1
    };
}Tuple Struct(结构体元组) 
可以定义类似 Tuple 元组的 Struct。
rust
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let white = Color(255,255,255);
let origin = Point(0,0,0);Struct 数据的所有权 
rust
struct User {
    username: String,
    email: String,
    age: usize,
    active: bool,
}- 这里的字段使用了 String 而不是&str 
- 只要 struct 实例是有效的,那么里面的字段数据也是有效的 
- Struct 里也可以存放引用,但是需要使用生命周期(后面补充) 
- 如果 struct 里存放引用但不使用生命周期就会报错。 
计算长方形面积 Demo 
rust
//对这个结构体使用调试模式,这个注解实际上使用的是std::fmt::Debug
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
fn main() {
    let rect = Rectangle {
        width: 10,
        height: 10,
    };
    println!("area is {}", area(&rect));
    //这里是为了能将rect里的信息更好的打印出来,对应的结构体上面记得加#[derive(Debug)],加#号会换行
    println!("{:#?}", rect);
}
fn area(rect: &Rectangle) -> u32 {
    rect.width * rect.height
}Struct 的方法 
- 方法和函数类似 
- 不同之处:方法在 Struct 中(或 enum、trait 对象)的上下文定义里 
- 方法第一个参数总是 self,表示方法被调用的 Struct 实例,后续跟着的是其它参数。 
方法定义 
- 在 impl 块里定义方法
- 方法第一个参数是&self 时是引用,不获得所有权,如果写 self 会获得当前结构体所有权,也可以使用 mut 关键数字实现可变借用
使用方法来重写上面的例子
rust
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
impl Rectangle {
    //引用Rectangle结构体
    fn area(&self) -> u32 {
        self.width * self.height
    }
}
fn main() {
    let rect = Rectangle {
        width: 10,
        height: 10,
    };
    println!("area is {}", rect.area());
    println!("{:#?}", rect);
}方法调用运算符 
Rust 会在调用方法时自动引用或解引用。
调用方法时,Rust 会根据情况自动添加 &、&mut 或 *(解引用符号),以便 object 可以匹配到方法的签名,比如说下面两行代码效果相同:
rust
p1.distance(&p2);
(&p1).distance(&p2);关联函数 
可以在 impl 块里定义不把 self 作为第一个参数的函数,叫关联函数(不叫方法了),类似于别的语言的静态方法 static。比如我们之前用得很多的String::from()就是一个关联函数。
- 关联函数常用于构造器
看个例子,下面就是关联函数的例子。
rust
#[derive(Debug)] //对这个结构体使用调试模式,这个注解实际上使用的是std::fmt::Debug
struct Rectangle {
    width: u32,
    height: u32,
}
impl Rectangle {
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}
fn main() {
    let rect = Rectangle::square(10);
    println!("{:?}", rect); //Rectangle { width: 10, height: 10 }
}到了现在,我们再来说说我们之前一直在使用到的两个冒号,::,这是干嘛用的呢?
- 可以使用于关联函数
- 模块创建的命名空间(后面讲)
多个 impl 块 
每个 struct 结构体可以拥有多个 impl 块。比如同名的 impl 块,里面放不同的方法(同一种类型的抽象可以这样但没必要)。
rust
struct Test {}
impl Test {
  fn test1() {}
}
impl Test {
  fn test2() {}
} 学习使我快乐
学习使我快乐