I'm just starting with Rust and since I'm a person who learns by doing I would like to fully understand the idiomatic way of solving cases like this in Rust.
Many replies I got in chat are all the same: "clone!".
I don't want to clone(), I'm here to learn better ways otherwise I'll go back to using Golang or Javascript.
Plus I'm afraid of cloning because I don't wanna allocate many times the same data (Config) in this case.
Even if I work with many workers (this is the case with actix-web) I wanna use references to that struct, not clone each time allocating many times the same data. Am I wrong?
In the simple below code as you can see I'm passing the struct Config by value to a function. In that function I need to refer to some fields of that struct and I'm havng serious troubles understanding how to do.
- main.rs:
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use std::net::SocketAddr;
#[tokio::main]
async fn main() {
let config = new_config();
start(config).await.unwrap();
}
#[derive(Clone)]
pub struct Config { // never changes during the app life, it's a read only once created at runtime
pub app_name: String,
pub port: String,
}
fn new_config() -> Config {
Config {
app_name: String::from("APP_NAME"),
port: String::from("1234"),
}
}
pub struct AppState {
pub config: Config,
}
async fn hello() -> impl Responder {
HttpResponse::Ok()
}
async fn start(config: Config) -> std::io::Result<()> {
println!("{}", config.app_name); //I'm using it the first time here
let server = HttpServer::new(move || { // I'm moving it here
App::new()
.app_data(web::Data::new(AppState { config })) // here I get an error: cannot move out of `config`, a captured variable in an `Fn` closure. move occurs because `config` has type `Config`, which does not implement the `Copy` trait rustc E0507
.route(&config.app_name, web::get().to(hello))
});
let addr = SocketAddr::from(([127, 0, 0, 1], config.port.parse::<u16>().unwrap())); // here another error: borrow of moved value: `config`. borrow occurs due to deref coercion to `str` rustc E0382
server.bind(("127.0.0.1", 8080))?.run().await
}
Can you help me understand what's the idiomatic way of doing this with Rust?