node to rust - deptno/deptno.github.io GitHub Wiki
24μΌ μ½μ€λ‘ node μλ ¨μλ€ μν λ¬μ€νΈ κ°μ΄λ
npm | cargo | |
---|---|---|
init | init | νμ¬ λλ ν 리 κΈ°μ€ |
new | λλ ν 리 ν¨κ» μμ± | |
run | build + execute | |
install | fetch | |
install [package_name] | add | |
uninstall | rm | |
install --global | install | ~/.cargo/bin |
test | test | |
publish | publish | |
run [start] | run --exmaple xxx | @todo |
benchmarks | bench | |
build | build | |
- | build --release | |
clean | clean | |
docs | doc --open | |
- | check | tsc --noEmit |
- | clippy | eslint |
npm κ³Ό λ¬λ¦¬ task runner λ₯Ό κ°μ§μ§ μμλ€. λλ¬Έμ μ¬μ μ΄ makefile μ΄ μ¬μ©λλ€.
μ μλ just
λ₯Ό μΆμ²
cargo install just
workspaces & monorepo
Cargo.toml
[workspace]
members = [
"crates/*"
]
[dependencies]
other-project = { path = "../other-project"}
- cargo-edit - λνλμ λ²μ λ³κ²½
- cargo-workspaces(cargo ws) - lerna like
- cargo-expand - macro
- tomlq - jq like
core plugin
- rust-analyzer
- vadimcn.vscode-lldb
- bungcip.better-toml
- crates
- search-crates-io
String vs &str
&str -> String μ νμ μν΄ .to_owned() λ₯Ό μ¬μ©νλ€.
- .to_string() μ Display trait μ μ§μνκΈ° μν λ©μλ
- .into() μ νκ²νμ μΌλ‘μ μ νμ μν From,Into trait μ ꡬν
arrayλ μ»΄νμΌ νμμ κΈΈμ΄μ λͺ¨λ μμκ° μ΄κΈ°ν λμ΄μΌνλ€. μΌλ°μ μΌλ‘ js λ§€μΉλλ건 VecDeque μΌλ‘ μλ°©ν₯ μ κ·Όμ΄ κ°λ₯νλ€.
- Vec
- VecDeque: μμͺ½μμ push, pop μ΄ κ°λ₯νλ€.
struct: μλ €μ§ ν€ μ μ κ°μ§ λ°μ΄ν° μ μ κ²½μ° map(hashmap): λͺ¨λ₯΄λ ν€μ + λμΌ νμ
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("key1", "value1");
map.insert("key2", "value2");
println!("{}", map.get("key1").unwrap_or(&""));
println!("{}", map.get("key2").unwrap_or(&""));
}
"" μ νμ
μ &str
map.get("key1")
μ νμ
μ Option<&&str> μ΄ λλ€.
&str μ΄κ³ get()
μ κ²½μ° μμ κΆ μ΄μ μ΄ λλ©΄ map μμ ν΄λΉ value κ° μ κ±°λμ΄μΌνκΈ° λλ¬Έμ borrowing(&) μ΄ λμΌνλ€.
struct A {
color: String
}
imple A {
pub fn new() -> {
Self {
color: "red".to_owned(),
}
}
}
-
new()
λ ν€μλκ° μλλΌ μ»¨λ²€μ μ΄λ€. -
#[derive(Debug)]
ꡬ문μ Trait μ default ꡬνμ μ 곡νλ€. - ν¨μλ κΈ°λ³Έμ μΌλ‘ private μ΄λ€.
- 첫λ²μ§Έ μΈμλ₯Ό self νΉμ &self λ‘ μ μΈνλ©΄ μΈμ€ν΄μ€ λ©μλκ° λλ€.
- self: Self
- &self: &Self
- self λ₯Ό μΈμλ‘ μ μΈνλ κ²½μ° μ€λμ½μ κ°μ§κ² λλ―λ‘ μ΄ν μΈμ€ν΄μ€λ₯Ό μκ² λλ€.
- μλ°μ€ν¬λ¦½μ .map() μ²λΌ μλ‘μ΄ μΈμ€ν΄μ€λ₯Ό λ§λ€μ΄μ λ°ννλ κ²½μ°
- μλ©Έμμ κ°μ μν μ νλ κ²½μ°
- λ©μλ 체μ΄λ enums μ union type μ μ²λ¦¬ν μ μλ€.
Trait μ μλ°μ€ν¬λ¦½νΈμ Mixins μ΄λ€. λ©μλμ μ§ν©μ΄λΌκ³ μκ°νλλ‘ νλ€.
- λͺ¨λ μ μλ privateμ΄ default
- trait methods, enum variants λ default κ° public
- visibility λ λͺ¨λμ κ²μ΄λ―λ‘ λͺ¨λ λ΄μμλ 무κ΄νκ² μ°Έμ‘°κ° κ°λ₯νλ€.
- pub(create) λ₯Ό ν΅ν΄ crate λ΄λΆμμ μ κ·Ό νμ©
- pub(super) λΆλͺ¨μκ²λ§ νμ©
ν¨μ μΈμλ &String, String μ΄ μλ &str λ‘νλ€.
-
String μ Borrow μ΄ κ΅¬νλμ΄μμ΄ μλ 컨λ²ν μ΄ λλ€.
-
Display ꡬνν¨μΌλ‘μ¨
.to_string()
μ μ»μ μ μλ€. -
Borrow<str>
- λ λ§μ κ°μ + μ€ν¨ν μ μλ€. -
@todo
AsRef<str>
- λ μ μ κ°μ + μ€ν¨ν μ μλ€.
std::prelue μ μ μΈλ κ²λ€μ use
μ μΈ μμ΄ μ¬μ©μ΄ κ°λ₯νλ€.
-
Some
-
None
-
unwrap()
μ Err(T), None μ΄ μ€λ κ²½μ° panic μ λ°μμν¨λ€. -
unwrap_or(v)
μ€ν¨ μμ΄ v λ₯Ό κΈ°λ³Έκ°μΌλ‘ λ¦¬ν΄ -
unwrap_or_else(|| {})
μ€ν¨ μμ΄ ν¨μλ₯Ό ν΅ν κ°μ λ¦¬ν΄ -
unwrap_or_default()
Default
trait μ ꡬνν κ²½μ°μ μ¬μ©λ¨
λ§€μ§ value λμ Option, Result λ₯Ό μ΄μ©νμ.
μλ‘ λ€λ₯Έ νμ μ μ€λ₯λ₯Ό λ°ν νλ ν¨μ μμ±νκΈ°
- Box
- Box λ μλͺ λ§νΌ μ‘΄μ¬νλ μ΄λ€ κ°μ μ£Όμ
- μν€ν μ³μ λΉνΈκ° ν¬κΈ°κ° λλ€.
- Result λ Err μ μ νμ΄ μμΌλ―λ‘ Error trait μ ꡬννμ§ μμ μ€λ₯κ° λ°μνλ©΄ μ€ν¨νλ€.
- custom Error type
impl std::error::Error for MyError {}
- supertraits trait μ΄ μμ‘΄νλ trait
-
From
,Into
,TryFrom
,TryInto
ꡬν νμ - From μ νκ² νμ μ λ³΄κ³ μλμΌλ‘ Into λ₯Ό νΈμΆνλ€.
-
Try*
μ μ€ν¨κ° κ°λ₯νλ€. λ¦¬ν΄ νμ μResult
κ° λλ€.
- Use crate
- thiserror - 컀μ€ν μλ¬, lib μμ μ£Όλ‘ μ¬μ©
#[derive(thiserror::Error, Debug)]
enum MyError {
#[error("Environment variable not found")]
EnvironmentVariableNotFound(#[from] std::env::VarError),
#[error(transparent)]
IOError(#[from] std::io::Error),
}
- anyhow - μλ³Έ μλ¬λ₯Ό κ·Έλλ‘ λ ΈμΆ, bin μμ μ¬μ©
- Fn
- FnMut
- FnOnce - move λ‘ μμ κΆμ μλ κ²½μ°
@todo impl [trait] μ ν¨μ μΈμ νΉμ λ¦¬ν΄ κ° μ΄μΈμλ μ¬μ©μ΄ λΆκ°λ₯νλ€. λλ¬Έμ dyn [trait] μΌλ‘ μ μ₯μ΄ νμνλ€. dyn [trait] μ unsized μ΄λ©° λ¬μ€νΈλ μ΄λ₯Ό μ’μνμ§ μλλ€.
@todo T: 'static
, &'static
μ λ€λ₯΄λ€
T: 'static
μ μμν μ§μλλ λ³μλ₯Ό μλ―Ένμ§ μλλ€.
- λ°°μ΄μ μλ €μ§ ν¬κΈ°μ μ΄κΈ°νλμ΄ μμ΄μΌνλ€.
- μλ°μ€ν¬λ¦½νΈμ Array λ Vec κ³Ό λ§€μΉλλ€.
- VecDeque λ μμͺ½μμ μ
μΆλ ₯μ΄ κ°λ₯νλ€.
- Vec -> vec![]
-
for prop in hashmap.keys() { }
->.keys()
λ μμ μμλ‘ μ‘°μ μ΄ λΆκ°λ₯ for i in 0..max { }
while ((data = obj.dowork())) { }
while let Some(data) = obj.dowork() { }
loop { break; }
'outer: loop { break 'outer; }
let value = loop { break "return value"; }
Iterator, Array, Vec -> ::iter()
-
Iterator λ lazy νκ² λμ
collect()
λ±μ λ°ν ν¨μλ₯Ό μ¬μ©ν λ iterator λ€μ λ©μλ λ€μ΄ μ¬μ© -
Vec::iter() λ‘ μμ± or Vec::iter_mut() -> Iterator λ₯Ό 리ν΄
-
Iterator.collect() λ‘ λ°ν -> νκ²μ νμ μ μ§μ ν΄μΌν¨ eg,
let a: Vec<_> = ...
-
Iterator.next() λ°λ³΅μμμ λ¨μΌ κ°μ μ»μλ μ¬μ©
-
Iterator.filter() 2μ€ μ°Έμ‘°
-
Iterator.find() == Iterator.filter().next(), js μ λ€λ₯΄κ² find() λ₯Ό μ¬λ¬λ² νΈμΆ κ°λ₯
-
Iterator.forEach() iterator μ¦μ μλΉ, μΌλ° 루νκ° μ νΈλλ€.
-
Vec|Array.join(",") js μ λμΌ
-
Vec.push()
Vec
λ§ κ°λ₯ -
Vec.pop()
Vec
λ§ κ°λ₯ -
VecDeque.push_front()
VecDeque
λ§ κ°λ₯ -
VecDeque.pop_front()
VecDeque
λ§ κ°λ₯
.collect()
λ₯Ό ν΅ν΄ νΉμ λ°μ΄ν° νμ
μ λ°ννμ§ λ§κ³ , Iterator μ체λ₯Ό λ°νν΄μ μ§μ°νκ°μ μ μ°μ±μ ν보νλλ‘ νλ€.
λ¬μ€νΈλ λ¬μ€νΈμ Promise μΈ Futures
λ₯Ό κ°μ§κ³ μλ€. κ·Έλ¬λ executor, reactor(node μ event loop) κ° μ‘΄μ¬νμ§ μλλ€.
μ΄μ λν ν΄λ¦¬νμ μλμ κ°λ€.
- tokio
- smol
- async-std
fn sync_fx() -> String {
}
async fn async_fx() -> String { // impl Future<Output = String>
}
#[tokio::main]
async fn main() {
let msg = async_fx().await;
}
node μ λ¬λ¦¬ .await
μ νκΈ°μ μλ μ€νλμ§ μλλ€.
λΉλκΈ° ν΄λ‘μ
let closure = || async {
println!("hello");
};
μ°λ λλ‘ μ μ‘λμ΄ μ¬μ©λλ κ²½μ° μΈμμ κ²½κ³λ₯Ό μ£Όμ΄μΌνλ€.
- 'static - μΈμ μ¬μ©λ μ§ λͺ¨λ₯΄κΈ° λλ¬Έ
- Send or Sync - Threadsafe
cargobook μ Cargo.lock
μ λΌμ΄λΈλ¬λ¦¬μμλ μλ΅νλΌκ³ μ‘°μΈν¨(λ²μ κ΄λ¦¬μμλ‘ μ΄ν΄)
./Cargo.toml
[workspace]
members = ["crates/*"]
./crates/my-lib/Cargo.toml
./crates/cli/Cargo.toml
...
[dependencies]
my-lib = { path = "../my-lib" }
cargo run crates/cli
cargo run -p cli
test
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}
λ΄λΆ ν
μ€νΈλ μ΄μ κ°μ λ°©μμΌλ‘λ§ νλ€.
tests λλ ν 리λ₯Ό λ§λ€μ΄μ μΈλΆμμ ν
μ€νΈνλ κ²½μ° pub
μ κ·Όμ§μμλ‘ μ€μ λ κ²½μ°μλ§ μ κ·Όκ°λ₯νλ€.
#cfg(flag)
flag κ·Έλ‘ on/off
[#test]
unit test -> cargo test
λ‘ μ€νλλ€.
assert ν¨μ
- assert!
- assert_eq!
- assert_ne!
crate μ΄λ¦μ νμ΄ν(-
)μ μ¬μ©νμ§λ§ μ½λμμ μ°Έμ‘°μμλ μΈλλ°(_
) λ‘ μ°Έμ‘°ν΄μΌλλ€.
- structopt
- log
- env_logger
RUST_LOG=debug cargo run -p cli
RUST_LOG=package_name=debug cargo run -p cli
use structopt::{clap::AppSettings, StructOpt};
#[derive(StructOpt)]
#[structopt(
name = "name",
about = "about",
global_settings(&[
AppSettings::ColoredHelp
]),
)]
struct CliOptions {
#[structopt(parse(from_os_str))]
pub(crate) file_path: PathBuf,
}
fn main() {
let options = CliOptions::from_args();
}
cargo run -p cli -- --help
cli μ μΈμλ₯Ό λ£μ΄μ μ€ννλ €λ©΄ --
νμ μΈμλ₯Ό μ
λ ₯νλ€.
#[derivte(StructOpt)]
μλ¬ νμμ λ³ννλ λ°©λ²
- From, Into, TryFrom, TryInto
- .map_err
fn fx() -> Result(Self, CustomError) {}
#...
.map_err(|e| CustomError::Something(e))?
}
μΉμ΄μ λΈλ¦¬(WebAssembly, μ΄ν wa)λ₯Ό μ§μνλ―λ‘ ν΄λΉ ν¬λ§·μΌλ‘ ν¬λ§·λ νμΌμ μ½μ΄μ κΈ°λ₯μ μν ν μ μλ€. wa λ μμ§ μλ²½νμ§ μλ€. μμ§ νμ€ μ€νμ΄ μμΌλ―λ‘ rpc μ κ°μ 컨μ μΌλ‘ μ²λ¦¬λ₯Ό μ§ννλ€.
- wapc_crate
- wapc
- wasmtime
- wasmtime-proivder
- https://wapc.io
- serde
- serde_json - json
- rmp_serde massage - pack
λ©ν° μ€λ λ μ½λλ₯Ό μμ±νλ€λ©΄ μ°λ λκ° λ°μ΄ν° μ΄λμ μν΄ μλ λκ°μ§ Traitμ΄ μ‘΄μ¬νλ€.
-
Send - λΆλ³ μ°Έμ‘°
-
Sync - κ°λ³ μ°Έμ‘°
-
Rc - Reference Count μ¬λ¬ μ°Έμ‘°κ° μ‘΄μ¬νκ³ κ·Έ μ°Έμ‘°κ° λͺ¨λ μ κ±°λμλ λ©λͺ¨λ¦¬λ₯Ό ν΄μ νλ€.
-
Arc - Atomic Reference Count,
Rc
μSend
λ²μ μ΄λ€. -
Mutex - ν μμ μ νλμ μ½κ³ μ°κΈ°λ§ κ°λ₯.
-
RwLock - Mutex λ³΄λ€ λ¬΄κ²λ€. μ¬λ¬ μ½κΈ°κ° κ°λ₯νλ©° ν μμ μ νλμ μ°κΈ°λ§ κ°λ₯νλ€.
-
parking_lot
-Mutex
,RwLock
λ³΄λ€ λΉ λ₯΄λ©°Result
λ₯Ό 리ν΄νμ§ μλλ€.
Mutex
, RwLock
λ±μ μ¬μ©ν λ λ½μ μ»μ λΈλ‘μ΄ μ¬λΌμ§λ©΄ λ½μ΄ μλμΌλ‘ ν΄μ λλ€.
μ‘°μ¬ν΄μΌν μ μ λ½μ μ»μ νμ .await
λ±μ λΉλκΈ° λμμ νκ² λλ©΄ λΆνμν λ½μ μ‘κ³ μκ²λλ€.
Tokio λ μ체 Sync crate λ₯Ό κ°μ§κ³ μλ€.