Rust简单整理(c7-c9)
by wqpw
基于官方教程《The Rust Programming Language》
7. Managing Growing Projects with Packages, Crates, and Modules
Packages: A Cargo feature that lets you build, test, and share crates
Crates: A tree of modules that produces a library or executable
Modules and use: Let you control the organization, scope, and privacy of paths
Paths: A way of naming an item, such as a struct, function, or module
pub, super::, pub use, use, as, Glob Operator(*), ......
8. Common Collections
fn main() {
vec_test();
string_test();
hashmap_test();
}
fn hashmap_test() {
use std::collections::HashMap; //one is the least often used
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
let teams = vec![String::from("Red"), String::from("Black")];
let init_scores = [20, 30];
let t = teams.iter().zip(init_scores.iter());
let scores2: HashMap<_, _> = t.collect();
let s1 = String::from("ttt");
let v1 = 20; //has Copy trait
scores.insert(s1, v1); //s1 moved. &s1
// references point to must be valid for at least as long as the hash map is valid
println!("{}", v1);
let team_name = String::from("Black");
println!("Black: {:?}", scores2.get(&team_name)); //Option<&V> Some(&30)
for (key, value) in &scores {
println!("{}: {}", key, value);
}
//update
scores.insert(String::from("Blue"), 233);
println!("{:?}", scores);
/*
return a mutable reference to the value for the corresponding Entry key
if that key exists, and if not,
inserts the parameter as the new value for this key
and returns a mutable reference to the new value.
*/
scores.entry(String::from("Blue")).or_insert(50);
//--------------------count words
let text = "hello world wonderful world";
let mut map = HashMap::new();
for word in text.split_whitespace() {
let count = map.entry(word).or_insert(0);
*count += 1;
}
println!("{:?}", map);
}
fn string_test() {
let mut s = String::new();
let data = "str233";
let data = data.to_string();
s = 1.to_string();
println!("{} {}", s, data);
let data = "go".to_string();
println!("{}", data);
let hello = String::from("你好"); //utf8
println!("{} {}", hello, "こんにちは");
let mut s = String::from("foo");
s.push_str("bar");
s.push('c');
println!("{}", s);
let s2 = "aaa";
s.push_str(s2); //takes a string slice not ownership!
println!("{}", s2);
let ss = s + &s2; //note ownership. s moved
//fn add(self, s: &str) -> String
// we can only add a &str to a String
//Rust coerce the &String argument into a &str.
//deref coercion, Rust turns &s2 into &s2[..]
println!("{}", ss);
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = s1 + "-" + &s2 + "-" + &s3; //just s1 moved
println!("{}", s2);
let s1 = String::from("tic");
let s = format!("{}-{}-{}", s1, s2, s3); //doesn’t take ownership
println!("{}", s);
//Rust strings don’t support indexing
//A String is a wrapper over a Vec<u8>
let len = String::from("Здравствуйте").len();
println!("{}", len); //24
let hello = "Здравствуйте";
let s = &hello[0..4]; //4 bytes
println!("{}", s);
for c in "中国人均GDP".chars() { //bytes()
println!("{}", c);
}
}
fn vec_test() {
let v: Vec<i32> = Vec::new();
let v = vec![1, 2]; //i32
let mut v = Vec::new();
v.push(5);
v.push(6);
let v = vec![1, 2, 3, 4];
let third: &i32 = &v[2]; //v[10] crash
println!("{}", third);
match v.get(2) { // -> Option<&T> get(10) None user-friendly
Some(third) => println!("{}", third),
None => println!("No third."),
}
for i in &v {
println!("i: {}", i);
}
let mut v = vec![1, 2, 3, 4];
for i in &mut v {
*i += 50;
println!("i+50: {}", i);
}
//known different types
enum SpreadsheetCell {
Int(i32),
Float(f64),
Text(String),
}
let row = vec![
SpreadsheetCell::Int(3),
SpreadsheetCell::Text(String::from("blue")),
SpreadsheetCell::Float(10.12),
];
for i in &row {
match i {
SpreadsheetCell::Int(i) => println!("{}", i),
SpreadsheetCell::Float(i) => println!("{}", i),
SpreadsheetCell::Text(i) => println!("{}", i),
}
}
}
9. Error Handling
use std::fs::File;
use std::io::ErrorKind;
use std::io::Read;
use std::io;
fn main() {
let f = File::open("hello.txt");
let f = match f {
Ok(file) => file,
Err(error) => match error.kind() {
ErrorKind::NotFound => match File::create("hello.txt") {
Ok(fc) => fc,
Err(e) => panic!("Problem creating the file: {:?}", e),
},
other_error => panic!("Problem opening the file: {:?}", other_error),
},
};
//no match
let f = File::open("hello.txt").unwrap_or_else(|error| {
if error.kind() == ErrorKind::NotFound {
File::create("hello.txt").unwrap_or_else(|error| {
panic!("Problem creating the file: {:?}", error);
})
} else {
panic!("Problem opening the file: {:?}", error);
}
});
//file handle or call default panic!
let f = File::open("hello.txt").unwrap();
//self-define msg pass to panic!
let f = File::open("hello.txt").expect("Failed to open hello.txt");
}
//Propagating Errors
fn read_username_from_file() -> Result<String, io::Error> {
let f = File::open("hello.txt");
let mut f = match f {
Ok(file) => file,
Err(e) => return Err(e),
};
let mut s = String::new();
match f.read_to_string(&mut s) {
Ok(_) => Ok(s),
Err(e) => Err(e),
}
}
//same functionality
//'?' convert error type automatically
fn _read_username_from_file() -> Result<String, io::Error> {
let mut f = File::open("hello.txt")?;
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
fn __read_username_from_file() -> Result<String, io::Error> {
let mut s = String::new();
File::open("hello.txt")?.read_to_string(&mut s)?;
Ok(s)
}
fn ___read_username_from_file() -> Result<String, io::Error> {
fs::read_to_string("hello.txt")
}
//The ? operator can only be used in functions that have a return type of Result
/*
fn main() -> Result<(), Box<dyn Error>> {
let f = File::open("hello.txt")?;
Ok(())
}
*/
//guess.rs
mod test {
pub struct Guess {
value: i32, //private
}
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
panic!("Guess value must be between 1 and 100, got {}.", value);
}
Guess {
value
}
}
pub fn value(&self) -> i32 {
self.value
}
}
}
fn main() {
use test::Guess;
let a = Guess::new(3);
println!("{}", a.value());
}