定义struct
使用struct关键字,并为整个struct命名 在花括号内,为所有字段(field)定义名称和类型
struct User {
username: String ,
email: String ,
sign_in_count: u64 ,
active: bool ,
}
实例化struct
为每个字段知道具体值 无需按声明的顺序进行指定
struct User {
username: String ,
email: String ,
sign_in_count: u64 ,
active: bool ,
}
fn main ( ) {
let user1 = User {
username: String :: from ( "xxxx" ) ,
email: String :: from ( "xxxx@163.com" ) ,
active: true ,
sign_in_count: 556 ,
} ;
println! ( "username:{}" , user1. username) ;
println! ( "email:{}" , user1. email) ;
println! ( "active:{}" , user1. active) ;
println! ( "sign_in_count:{}" , user1. sign_in_count) ;
}
取得struct里面的某个值
struct User {
username: String ,
email: String ,
sign_in_count: u64 ,
active: bool ,
}
fn main ( ) {
let mut user1 = User {
username: String :: from ( "xxxx" ) ,
email: String :: from ( "xxxx@163.com" ) ,
active: true ,
sign_in_count: 556 ,
} ;
user1. username = String :: from ( "hhhhhhh" ) ;
println! ( "username:{}" , user1. username) ;
println! ( "email:{}" , user1. email) ;
println! ( "active:{}" , user1. active) ;
println! ( "sign_in_count:{}" , user1. sign_in_count) ;
}
注意
一旦struct的实例是可变的,那么实例中的所有字段都是可以变的
struct作为函数的放回值
struct User {
username: String ,
email: String ,
sign_in_count: u64 ,
active: bool ,
}
fn build_user ( email: String , username: String ) -> User {
User {
email: email,
username: username,
active: true ,
sign_in_count: 1 ,
}
}
fn main ( ) {
let email = String :: from ( "xxxx@163.com" ) ;
let username = String :: from ( "llllll" ) ;
let user1 = build_user ( email, username) ;
println! ( "username:{}" , user1. username) ;
println! ( "email:{}" , user1. email) ;
println! ( "active:{}" , user1. active) ;
println! ( "sign_in_count:{}" , user1. sign_in_count) ;
}
字段初始化简写
当字段名与字段值对应变量名相同时,就可以使用字段初始化简写的方式
fn build_user ( email: String , username: String ) -> User {
User {
email,
username,
active: true ,
sign_in_count: 1 ,
}
}
struct更新语法
当你想基于某个struct实例来创建一个新实例的时候,可以使用struct更新语法
struct User {
username: String ,
email: String ,
sign_in_count: u64 ,
active: bool ,
}
fn build_user ( email: String , username: String ) -> User {
User {
email,
username,
active: true ,
sign_in_count: 1 ,
}
}
fn main ( ) {
let email = String :: from ( "xxxx@163.com" ) ;
let username = String :: from ( "llllll" ) ;
let user1 = build_user ( email, username) ;
let user2 = User {
email: String :: from ( "user2@163.com" ) ,
.. user1
} ;
println! ( "username:{}" , user2. username) ;
println! ( "email:{}" , user1. email) ;
println! ( "email:{}" , user2. email) ;
println! ( "active:{}" , user1. active) ;
println! ( "sign_in_count:{}" , user1. sign_in_count) ;
}
tuple struct
可定义类似tuple的struct,叫做tuple struct
tuple struct 整体有个名,但里面的元素没有名 适用:想给整个tuple起名,并且它不同于其它tuple,而且又不需要给每个元素
定义tuple struct:使用struct关键字,后边是名字,以及里面元素的类型
struct Color ( i32 , i32 , i32 ) ;
struct Point ( i32 , i32 , i32 ) ;
let black = Color ( 0 , 2 , 3 ) ;
let origin = Point ( 3 , 2 , 3 ) ;
Unit-Like Struct(没有任何字段)
可以定义没有任何的struct,叫做Unit-Like struct(因为与{},单元类型类似) 使用与需要在某个类型上失效某个trait,但是在里面有没有想要存储的数据结构
struct数据的所有权
struct User {
username: String ,
email: String ,
sign_in_count: u64 ,
active: bool ,
}
改struct实例拥有其所有的数据 只有struct实例是有效的,那么里面的字段也是有效的
struct里面也是存放引用,但是需要使用生命周期
什么事struct
std::fmt::Display std::fmt::Debug #[derive(Debug)] {:?} {:#?}
#[derive(Debug)]
struct Rectangle {
width: u32 ,
length: u32 ,
}
fn main ( ) {
let rect = Rectangle {
width: 22 ,
length: 44 ,
} ;
println! ( "{}" , area ( & rect) ) ;
println! ( "{:?}" , rect) ;
println! ( "{:#?}" , rect) ;
}
fn area ( rect: & Rectangle ) -> u32 {
rect. length * rect. width
}
struct的方法
方法和函数类似:fn关键字、名称、参数、返回值 方法与函数不同之处
方法是在struct(或enum、trait对象)的上下文中定义 第一个参数是self,表示方法被调用的struct实例
定义方法
#[derive(Debug)]
struct Rectangle {
width: u32 ,
length: u32 ,
}
impl Rectangle {
fn area ( & self ) -> u32 {
self . width * self . length
}
}
fn main ( ) {
let rect = Rectangle {
width: 33 ,
length: 44 ,
} ;
println! ( "{}" , rect. area ( ) ) ;
println! ( "{:#?}" , rect) ;
}
在impl块里定义方法 方法的第一个参数可以是&self,也可以获得其所有权或可变借用。其他参数一样。 更良好的代码组织。
方法调用的运算符
C/C++:object->somthing()和(*object).something()一样 rust没有->运算符 rust会自动引用或解引用
在调用方法时就会发生这种行为
在调用方法时,rust根据情况自动添加&、&mut或*,以便object可以匹配方法的签名。 下面两行代码效果相同
p1. distance ( & p2) ;
( & p1) . distance ( & p2) ;
关联函数
可以在impl块里定义不把self作为第一个参数的函数,它们叫做关联函数(不是方法)
String :: from ( ) ;
关联函数 模块创建的命名空间
#[derive(Debug)]
struct Rectangle {
width: u32 ,
length: u32 ,
}
impl Rectangle {
fn square ( width: u32 , length: u32 ) -> Rectangle {
Rectangle {
width,
length,
}
}
}
fn main ( ) {
let rect = Rectangle :: square ( 33 , 11 ) ;
println! ( "width:{}" , rect. width) ;
println! ( "length:{}" , rect. length) ;
println! ( "{:#?}" , rect) ;
}
多个impl块