impl Message { fn call(&self) { // method body would be defined here } }
let m = Message::Write(String::from("hello")); m.call(); }
enum option
1 2 3 4 5 6 7
![allow(unused_variables)] fn main() { enum Option<T> { //<T> means the Some variant of the Option enum can hold one piece of data of any type Some(T), None, } }
option不用显示引入,已经提前有了
1 2 3 4 5 6
fn main() { let some_number = Some(5); let some_string = Some("a string");
let absent_number: Option<i32> = None; }
If we use None rather than Some, we need to tell Rust what type of Option<T> we have Option and T (where T can be any type) are different types, In other words, you have to convert an Option to a T before you can perform T operations with it.
The code associated with each arm is an expression, and the resulting value of the expression in the matching arm is the value that gets returned for the entire match expression.
_省略The _ pattern will match any value.The () is just the unit value
if let
care about only one of the cases. For this situation, Rust provides if let.
1 2 3 4 5 6 7
fn main() { let some_u8_value = Some(0u8); if let Some(3) = some_u8_value { println!("three"); } }
1 2 3 4 5 6 7 8 9
fn main() { let coin = Coin::Penny; let mut count = 0; if let Coin::Quarter(state) = coin { println!("State quarter from {:?}!", state); } else { count += 1; } }
1 2 3 4 5 6 7 8 9 10
fn main() { let coin = Coin::Penny; let mut count = 0; match coin { Coin::Quarter(state) => println!("State quarter from {:?}!", state), _ => count += 1, } }
packages>crates>modules
A package isone or more cratesthat provide a set of functionality. A package contains a Cargo.toml file that describes how to build those crates. A package must contain zero or one library crates, and no more. It can contain as many binary crates as you’d like, but it must contain at least one crate (either library or binary). If a package contains src/main.rs and src/lib.rs, it has two crates: a library and a binary, both with the same name as the package. A package canhave multiple binary crates by placing files in the src/bin directory:each file will be a separate binary crate.
the use keyword that brings a path into scope; and the pub keyword to make items public. We’ll also discuss the as keyword, external packages, and the glob operator
Modules let us organize code within a crate into groups
Create a new library named restaurant by running cargo new --lib restaurant; crate //implicit module src/main.rs and src/lib.rs 产生 └── front_of_house ├── hosting │ ├── add_to_waitlist │ └── seat_at_table └── serving ├── take_order ├── serve_order └── take_payment
If we want to call a function, we need to know its path. A path can take two forms:
An absolute path starts from a crate root by using a crate name or a literal crate. A relative path starts from the current module and uses self, super, or an identifier in the current module. Both absolute and relative paths are followed by one or more identifiers separated by double colons (::).
1 2 3 4 5 6 7 8 9 10 11 12 13 14
mod front_of_house { mod hosting { fn add_to_waitlist() {} } }
mod back_of_house { fn fix_incorrect_order() { cook_order(); super::serve_order(); }
fn cook_order() {} }
Enums aren’t very useful unless their variants are public; it would be annoying to have to annotate all enum variants with pub in every case, so the default for enum variants is to be public. Structs are often useful without their fields being public, so struct fields follow the general rule of everything being private by default unless annotated with pub.
There’s another solution to the problem of bringing two types of the same name into the same scope with use: after the path, we can specify as and a new local name, or alias, for the type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
![allow(unused_variables)] fn main() { use std::fmt::Result; use std::io::Result as IoResult;
this technique is called re-exporting because we’re bringing an item into scope but also making that item available for others to bring into their scope
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } }
pub use crate::front_of_house::hosting; //其他可以 另外创立一个链接
fn main() { let v = vec![1, 2, 3]; //类别自己推测 } fn main() { let mut v = Vec::new();
v.push(5); v.push(6); v.push(7); v.push(8); } fn main() { { let v = vec![1, 2, 3, 4];
// do stuff with v } // <- v goes out of scope and is freed here }
1 2 3 4 5 6 7 8 9 10 11 12
fn main() { let v = vec![1, 2, 3, 4, 5];
let third: &i32 = &v[2]; println!("The third element is {}", third);
match v.get(2) { //gives us an Option<&T>. Some(third) => println!("The third element is {}", third), None => println!("There is no third element."), } }
1 2 3 4 5 6
fn main() { let mut v = vec![100, 32, 57]; for i in &mut v { *i += 50; //解引用 dereference operator (*) to get to the value in i } }
fn main() { let hello = String::from("السلام عليكم"); let hello = String::from("Dobrý den"); let hello = String::from("Hello"); let hello = String::from("שָׁלוֹם"); let hello = String::from("नमस्ते"); let hello = String::from("こんにちは"); let hello = String::from("안녕하세요"); let hello = String::from("你好"); let hello = String::from("Olá"); let hello = String::from("Здравствуйте"); let hello = String::from("Hola"); }
fn main() { let mut s = String::from("foo"); s.push_str("bar"); }
fn main() { let mut s = String::from("lo"); s.push('l'); }
push method takesa single character
1 2 3 4 5
fn main() { let s1 = String::from("Hello, "); let s2 = String::from("world!"); let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used//be moved into the add call and no longer be valid after that. }
add is that the compiler can coerce the &String argument into a &str
format
1 2 3 4 5 6 7
fn main() { let s1 = String::from("tic"); let s2 = String::from("tac"); let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3); //doesn’t take ownership of any of its parameters. }
utf-8 可变字节 1-4字节,有些一个字节 有些4个字节
1 2 3 4 5 6
[allow(unused_variables)] fn main() { let hello = "Здравствуйте";
#![allow(unused_variables)] fn main() { for b in"नमस्ते".bytes() { // returns each raw byte, println!("{}", b); } }
hashmap
all of the keys must have the same type, and all of thevaluesmust have the same type.
1 2 3 4 5 6
fn main() { use std::collections::HashMap; let mut scores = HashMap::new(); scores.insert(String::from("Blue"), 10); scores.insert(String::from("Yellow"), 50); }
1 2 3 4 5 6 7 8 9
fn main() { use std::collections::HashMap;
let teams = vec![String::from("Blue"), String::from("Yellow")]; let initial_scores = vec![10, 50];
let mut scores: HashMap<_, _> = teams.into_iter().zip(initial_scores.into_iter()).collect(); }
zip method to create a vector of tuples collect method to turn that vector of tuples into a hash map,
For types that implement the Copy trait, like i32, the values are copied into the hash map. For owned values like String, the values will be moved and the hash map will be the owner of those values
let team_name = String::from("Blue"); let score = scores.get(&team_name); }
Some(&10). The result is wrapped in Some because get returns an Option<&V> no value get will return None.
for (key, value) in &scores {
println!("{}: {}", key, value);
}
1 2 3 4 5 6 7 8 9 10 11 12
fn main() { use std::collections::HashMap;
let mut scores = HashMap::new(); scores.insert(String::from("Blue"), 10);
scores.entry(String::from("Yellow")).or_insert(50); //entry检查值是否存在,返回Entry, or_insert是Entry的方法 return a mutable reference to the value 没有值插入 scores.entry(String::from("Blue")).or_insert(50);
for word in text.split_whitespace() { let count = map.entry(word).or_insert(0); //or_insert method actually returns a mutable reference (&mut V) 所以可以加1 *count += 1; }