Write a basic hello world in Rust!
rustc file.rsproduces an executable calledfile.- Normally, for larger projects you would use
cargo. Cargo also does package management. - Try
cargo new --bin hello_worldandcargo runin the directory created.
fn main() {
println!("Example!");
}Create a function which takes a String (call .to_string() on a string literal), and prints it out.
Make sure it compiles and runs as you expect.
Call that function a second time in the main function, and see why it fails to compile.
Understand how to fix that, and what it means.
Trying this with numbers may give a different result.
They implement the Copy trait, which means they can be automatically copied to pass into a function.
fn main() {
let value = 123;
foo(value);
}
fn foo(val: u32) {
println!("Val: {}", val);
}Create a program which uses the std::thread::spawn function to print from multiple threads in parallel.
Modify your program to print the number of the thread.
- May need
moveon closure to capture index. - Also you may wish to use
thread::sleeporJoinHandle::join.
use std::thread;
use std::time::Duration;
fn main() {
thread::spawn(|| println!("A thread!"));
thread::sleep(Duration::from_secs(1));
}Create a mutable integer which can be shared across threads, and add up 1 to 10 with 10 threads.
Try it with Atomics, or a Mutex.
The Rust compiler guarantees that your code will not have any data races, so you can parallelise your code with confidence. (Though it wont catch general race conditions, such as deadlocks)
std::sync::atomic::{AtomicUsize, Ordering};std::sync::Mutex;AtomicUsizehas thefetch_addmethod.- Atomics - For Ordering just use
Ordering::SeqCst, the other options are complex and subtleSeqCstwill do what you want (though maybe very slightly slower). Mutex-Mutex::lock()returns aMutexGaurd.MutexGaurdimplements theDereftrait, which allows you to use*valto access the value. auto-dereferencing means this sometimes isn't required, as in the below example.
use std::sync::{Arc,Mutex};
use std::thread;
use std::time::Duration;
pub fn main() {
let xs = vec![];
let axs = Arc::new(Mutex::new(xs));
for _ in 0..10 {
let axs = axs.clone();
thread::spawn(move || {
let mut v = axs.lock().unwrap();
v.push(1)
});
}
thread::sleep(Duration::from_secs(1));
println!("Sum: {:?}", axs);
}- Create a small program that prints if a given file exists or not.
- Use suitable error handling.
- Extend your program to read and print the contents of the file.
::std::fs::File::openis a function which returns aResult<File, Error>
use std::net::TcpStream;
use std::io::Read;
fn main() {
if let Ok(mut stream) = TcpStream::connect("127.0.0.1:8080") {
println!("Connected to the server!");
let mut data = String::new();
if stream.read_to_string(&mut data).is_err() {
println!("Error reading from server...");
};
println!("{}", data);
} else {
println!("Error connecting to server...");
}
}Create a basic TCP server which responds with "hello world"
- You probably want
std::net::TcpListenerhere.
- Create a TCP server which responds with a hash of the received data.
- Extend this by handling each request in it's own thread.
- Extend this further by storing computed requests in a central cache (Try
std::collections::HashMapin aMutex)
You may use this hash function, or if you have an internet connection try using the md5 Crate.
use std::hash::Hash;
fn calculate_hash<T: Hash>(t: &T) -> u64 {
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
let mut s = DefaultHasher::new();
t.hash(&mut s);
s.finish()
}