第14ç« éå
# 第14ç« éå
æ¯æç¯å¢ï¼ä»å¤©å°±å建ä¸ä¸ªéå ï¼ ââç§é©¬å Â·å¼æçº³æ ¹ï¼Cormac Flanaganï¼
å¯¹æ´æ°åéè¿è¡æåºå¾ç®åï¼
integers.sort();
ç¶èï¼ä»¤äººéæ¾çæ¯ï¼å½æä»¬æ³è¦å¯¹æäºæ°æ®è¿è¡æåºæ¶ï¼è¿äºæ°æ®å¾å°æ¯æ´æ°åéãé常æä»¬æ¥æçæ¯æç§è®°å½ï¼èå ç½®çæåºæ¹æ³éå¸¸æ æ³ç´æ¥ä½¿ç¨ï¼
struct City {
name: String,
population: i64,
country: String,
...
}
fn sort_cities(cities: &mut Vec<City>) {
cities.sort(); // é误ï¼ä½ 叿æä»ä¹æ¹å¼å¯¹å®ä»¬è¿è¡æåºï¼
}
2
3
4
5
6
7
8
9
10
Rust伿¥éï¼æç¤ºCityæªå®ç°std::cmp::Ordãæä»¬éè¦æå®æåºé¡ºåºï¼å¦ä¸æç¤ºï¼
/// æäººå£æ°é对åå¸è¿è¡éåºæåºçè¾
å©å½æ°ã
fn city_population_descending(city: &City) -> i64 {
-city.population
}
fn sort_cities(cities: &mut Vec<City>) {
cities.sort_by_key(city_population_descending); // æ£å¸¸
}
2
3
4
5
6
7
8
è¾
å©å½æ°city_population_descendingæ¥åä¸ä¸ªCityè®°å½ï¼å¹¶æååºé®ï¼å³æä»¬æ³è¦ç¨äºå¯¹æ°æ®è¿è¡æåºçåæ®µï¼å®è¿åä¸ä¸ªè´æ°ï¼æ¯å 为sortæ¹æ³æååºæåæ°åï¼èæä»¬å¸ææéåºæåï¼å³äººå£æå¤çå叿å¨åé¢ï¼ãsort_by_keyæ¹æ³å°è¿ä¸ªé®å½æ°ä½ä¸ºåæ°ã
è¿ç§æ¹æ³å¯è¡ï¼ä½å°è¾ å©å½æ°åæéå ï¼ä¸ç§å¿å彿°è¡¨è¾¾å¼ï¼ä¼æ´å ç®æ´ï¼
fn sort_cities(cities: &mut Vec<City>) {
cities.sort_by_key(|city| -city.population);
}
2
3
è¿éçéå
æ¯|city| -city.populationã宿¥åä¸ä¸ªåæ°cityï¼å¹¶è¿å-city.populationãRust伿 ¹æ®éå
çä½¿ç¨æ¹å¼æ¨æå
¶åæ°ç±»ååè¿åç±»åã
æ ååºä¸å ¶ä»æ¥åéå çåè½ç¤ºä¾å æ¬ï¼
- è¿ä»£å¨æ¹æ³ï¼å¦
mapåfilterï¼ç¨äºå¤çé¡ºåºæ°æ®ãæä»¬å°å¨ç¬¬15ç« ä»ç»è¿äºæ¹æ³ã - 线ç¨ç¸å
³çAPIï¼å¦
thread::spawnï¼å®ç¨äºå¯å¨ä¸ä¸ªæ°çç³»ç»çº¿ç¨ãå¹¶åç¼ç¨å°±æ¯å°å·¥ä½åé å°å ¶ä»çº¿ç¨ï¼èéå å¯ä»¥å¾æ¹ä¾¿å°è¡¨ç¤ºå·¥ä½åå ãæä»¬å°å¨ç¬¬19ç« ä»ç»è¿äºç¹æ§ã - ä¸äºææ¡ä»¶å°éè¦è®¡ç®é»è®¤å¼çæ¹æ³ï¼æ¯å¦
HashMapæ¡ç®çor_insert_withæ¹æ³ãè¿ä¸ªæ¹æ³ç¨äºå¨HashMapä¸è·åæå建ä¸ä¸ªæ¡ç®ï¼å½è®¡ç®é»è®¤å¼çå¼éè¾å¤§æ¶ä¼ä½¿ç¨å®ãé»è®¤å¼éè¿éå ä¼ å ¥ï¼åªæå¨å¿ é¡»åå»ºæ°æ¡ç®æ¶æä¼è°ç¨è¿ä¸ªéå ã
å½ç¶ï¼å¦ä»å¿å彿°éå¤å¯è§ï¼å³ä½¿å¨æå没æå¿å彿°çè¯è¨ï¼å¦JavaãC#ãPythonåC++ä¸ä¹æ¯å¦æ¤ãä»ç°å¨å¼å§ï¼æä»¬åè®¾ä½ ä¹åå·²ç»è§è¿å¿å彿°ï¼å¹¶éç¹å ³æ³¨Rustéå çç¬ç¹ä¹å¤ã卿¬ç« ä¸ï¼ä½ å°å¦ä¹ ä¸ç§ç±»åçéå ï¼å¦ä½å¨æ ååºæ¹æ³ä¸ä½¿ç¨éå ï¼éå å¦ä½âæè·âå ¶ä½ç¨åä¸çåéï¼å¦ä½ç¼åæ¥åéå ä½ä¸ºåæ°ç彿°åæ¹æ³ï¼ä»¥åå¦ä½åå¨éå 以便ç¨åä½ä¸ºåè°ä½¿ç¨ãæä»¬è¿å°è§£éRustéå çå®ç°æ¹å¼ï¼ä»¥åå®ä»¬æ¯ä½ æ³è±¡ä¸æ´å¿«çåå ã
# æè·åé
éå å¯ä»¥ä½¿ç¨å±äºå å«å®ç彿°çæ°æ®ãä¾å¦ï¼
/// æ ¹æ®ä¸åçç»è®¡æ°æ®è¿è¡æåºã
fn sort_by_statistic(cities: &mut Vec<City>, stat: Statistic) {
cities.sort_by_key(|city| -city.get_statistic(stat));
}
2
3
4
è¿éçéå
使ç¨äºstatï¼å®ç±å
å«å®ç彿°sort_by_statisticææ¥æãæä»¬è¯´éå
âæè·âäºstatãè¿æ¯éå
çç»å
¸ç¹æ§ä¹ä¸ï¼Rustèªç¶ä¹æ¯æï¼ä½å¨Rustä¸ï¼è¿ä¸ªç¹æ§æä¸äºéè¦æ³¨æçå°æ¹ã
å¨å¤§å¤æ°æ¯æéå çè¯è¨ä¸ï¼åå¾åæ¶èµ·çéè¦ä½ç¨ãä¾å¦ï¼èèä¸é¢è¿æ®µJavaScript代ç ï¼
// å¯å¨ä¸ä¸ªå¨ç»ï¼éæ°æååå¸è¡¨æ ¼ä¸çè¡ã
function startSortingAnimation(cities, stat) {
// ç¨äºå¯¹è¡¨æ ¼è¿è¡æåºçè¾
å©å½æ°ã
// 注æè¿ä¸ªå½æ°å¼ç¨äºstatã
function keyfn(city) {
return city.get_statistic(stat);
}
if (pendingSort)
pendingSort.cancel();
// ç°å¨å¯å¨ä¸ä¸ªå¨ç»ï¼å°keyfnä¼ éç»å®ã
// æåºç®æ³ç¨åä¼è°ç¨keyfnã
pendingSort = new SortingAnimation(cities, keyfn);
}
2
3
4
5
6
7
8
9
10
11
12
13
éå
keyfnåå¨å¨æ°çSortingAnimation对象ä¸ï¼å®ä¼å¨startSortingAnimationè¿åå被è°ç¨ãé常ï¼å½ä¸ä¸ªå½æ°è¿åæ¶ï¼å®çææåéååæ°é½ä¼è¶
åºä½ç¨å并被丢å¼ãä½å¨è¿éï¼JavaScript弿å¿
须以æç§æ¹å¼ä¿çstatï¼å 为éå
使ç¨äºå®ã大夿°JavaScript弿éè¿å¨å ä¸åé
stat并让åå¾åæ¶å¨ç¨å忶宿¥å®ç°è¿ä¸ç¹ã
Rust没æåå¾åæ¶æºå¶ï¼é£ä¹å®æ¯å¦ä½å·¥ä½çå¢ï¼ä¸ºäºåçè¿ä¸ªé®é¢ï¼æä»¬æ¥ç两个ä¾åã
# åç¨åéçéå
é¦å ï¼è®©æä»¬é夿¬èå¼å¤´çä¾åï¼
/// æ ¹æ®ä¸åçç»è®¡æ°æ®è¿è¡æåºã
fn sort_by_statistic(cities: &mut Vec<City>, stat: Statistic) {
cities.sort_by_key(|city| -city.get_statistic(stat));
}
2
3
4
å¨è¿ç§æ
åµä¸ï¼å½Rustå建éå
æ¶ï¼å®ä¼èªå¨åç¨ä¸ä¸ªæåstatçå¼ç¨ãè¿æ¯åççï¼éå
å¼ç¨äºstatï¼æä»¥å®å¿
é¡»æä¸ä¸ªå¯¹statçå¼ç¨ã
å
¶ä½é¨åå¾ç®åãéå
éµå¾ªæä»¬å¨ç¬¬5ç« ä¸æè¿°çåç¨åçå½å¨æè§åãç¹å«å°ï¼ç±äºéå
å
å«ä¸ä¸ªå¯¹statçå¼ç¨ï¼Rustä¸ä¼è®©éå
ççå½å¨æè¶
è¿statãç±äºéå
åªå¨æåºæé´ä½¿ç¨ï¼æä»¥è¿ä¸ªä¾å没æé®é¢ã
ç®èè¨ä¹ï¼Rustéè¿ä½¿ç¨çå½å¨æè䏿¯åå¾åæ¶æ¥ç¡®ä¿å®å
¨æ§ãRustçæ¹å¼æ´å¿«ï¼å³ä½¿æ¯å¿«éçåå¾åæ¶å¨åé
ï¼ä¹ä¼æ¯Rustå¨è¿ç§æ
åµä¸å°statåå¨å¨æ ä¸çé度æ
¢ã
# çªååéçéå
第äºä¸ªä¾åæ´å¤æä¸äºï¼
use std::thread;
fn start_sorting_thread(mut cities: Vec<City>, stat: Statistic) -> thread::JoinHandle<Vec<City>> {
let key_fn = |city: &City| -> i64 { -city.get_statistic(stat) };
thread::spawn(|| {
cities.sort_by_key(key_fn);
cities
})
}
2
3
4
5
6
7
8
9
è¿æ´ç±»ä¼¼äºæä»¬ä¹åçJavaScript示ä¾ï¼thread::spawnæ¥åä¸ä¸ªéå
ï¼å¹¶å¨ä¸ä¸ªæ°çç³»ç»çº¿ç¨ä¸è°ç¨å®ã注æï¼||æ¯éå
çç©ºåæ°å表ã
æ°çº¿ç¨ä¸è°ç¨è
å¹¶è¡è¿è¡ãå½éå
è¿åæ¶ï¼æ°çº¿ç¨éåºï¼éå
çè¿åå¼ä½ä¸ºJoinHandleå¼è¿åç»è°ç¨çº¿ç¨ãæä»¬å°å¨ç¬¬19ç« ä»ç»è¿ä¸ç¹ï¼ã
åæ ·ï¼éå
key_fnå
å«ä¸ä¸ªå¯¹statçå¼ç¨ãä½è¿ä¸æ¬¡ï¼Rustæ æ³ä¿è¯è¿ä¸ªå¼ç¨çä½¿ç¨æ¯å®å
¨çãå æ¤ï¼Rust伿ç»è¿ä¸ªç¨åºï¼
error[E0373]: closure may outlive the current function, but it borrows `stat`,
which is owned by the current function
--> closures_sort_thread.rs:33:18
|
33 | let key_fn = |city: &City| -> i64 { -
^^^^^^^^^^^^^^^^^^^^ ^^^^
city|.get_statistic(stat) };
| | `stat`
is borrowed here
| may outlive borrowed value `stat`
2
3
4
5
6
7
8
9
10
å®é
ä¸ï¼è¿éæä¸¤ä¸ªé®é¢ï¼å 为citiesä¹è¢«ä¸å®å
¨å°å
±äº«äºãç®åå°è¯´ï¼ä¸è½ææthread::spawnåå»ºçæ°çº¿ç¨å¨å½æ°ç»ææ¶citiesåstatè¢«éæ¯ä¹å宿工ä½ã
è§£å³è¿ä¸¤ä¸ªé®é¢çæ¹æ³æ¯ä¸æ ·çï¼åè¯Rustå°citiesåstatç§»å¨å°ä½¿ç¨å®ä»¬çéå
ä¸ï¼è䏿¯åç¨å®ä»¬çå¼ç¨ã
fn start_sorting_thread(mut cities: Vec<City>, stat: Statistic) -> thread::JoinHandle<Vec<City>> {
let key_fn = move |city: &City| -> i64 { -city.get_statistic(stat) };
thread::spawn(move || {
cities.sort_by_key(key_fn);
cities
})
}
2
3
4
5
6
7
æä»¬æåçå¯ä¸æ´æ¹æ¯å¨ä¸¤ä¸ªéå
åé¢é½æ·»å äºmoveå
³é®åãmoveå
³é®ååè¯Rustï¼éå
ä¸ä¼åç¨å®ä½¿ç¨çåéï¼èæ¯çªåå®ä»¬ã
第ä¸ä¸ªéå
key_fnè·åstatçæææãç¶åï¼ç¬¬äºä¸ªéå
è·åcitiesåkey_fnçæææã
å æ¤ï¼Rust为éå æä¾äºä¸¤ç§ä»å å«ä½ç¨åè·åæ°æ®çæ¹å¼ï¼ç§»å¨ååç¨ãå®é ä¸ï¼é¤æ¤ä¹å¤æ²¡ææ´å¤éè¦è¯´æçäºï¼éå éµå¾ªæä»¬å¨ç¬¬4ç« å第5ç« ä¸å·²ç»ä»ç»è¿çç§»å¨ååç¨è§åã以䏿¯å ä¸ªå ·ä½ç¤ºä¾ï¼
- å°±åå¨Rustè¯è¨çå
¶ä»å°æ¹ä¸æ ·ï¼å¦æéå
è¦ç§»å¨ä¸ä¸ªå¯å¤å¶ç±»åï¼å¦
i32ï¼çå¼ï¼å®ä¼å¤å¶è¿ä¸ªå¼ãæä»¥ï¼å¦æStatistic碰巧æ¯ä¸ä¸ªå¯å¤å¶ç±»åï¼å³ä½¿å¨å建äºä½¿ç¨å®çmoveéå ä¹åï¼æä»¬ä»ç¶å¯ä»¥ä½¿ç¨statã - ä¸å¯å¤å¶ç±»åï¼å¦
Vec<City>ï¼çå¼ç¡®å®ä¼è¢«ç§»å¨ï¼åé¢ç代ç éè¿moveéå å°cities转移å°äºæ°çº¿ç¨ä¸ãå¨å建éå ä¹åï¼Rustä¸å 许æä»¬åéè¿å称访é®citiesã - 碰巧å¨è¿ä¸ªä»£ç ä¸ï¼å¨éå
ç§»å¨
citiesä¹åæä»¬ä¸éè¦å使ç¨å®ãä¸è¿ï¼å¦æç¡®å®éè¦ä½¿ç¨ï¼è§£å³æ¹æ³ä¹å¾ç®åï¼æä»¬å¯ä»¥åè¯Rustå écitiesï¼å¹¶å°å¯æ¬åå¨å¨å¦ä¸ä¸ªåéä¸ãéå åªä¼çªåå ¶ä¸ä¸ä¸ªå¯æ¬ï¼æ 论å®å¼ç¨çæ¯åªä¸ªå¯æ¬ã
éè¿æ¥åRustçä¸¥æ ¼è§åï¼æä»¬è·å¾äºéè¦çä¸è¥¿ï¼çº¿ç¨å®å ¨æ§ãæ£æ¯å 为åé被移å¨ï¼è䏿¯å¨å¤ä¸ªçº¿ç¨ä¹é´å ±äº«ï¼æä»¬æç¥éæ§çº¿ç¨ä¸ä¼å¨æ°çº¿ç¨ä¿®æ¹åéæ¶éæ¾å®ã
# 彿°åéå ç±»å
卿¬ç« ä¸ï¼æä»¬çå°å½æ°åéå é½å¯ä»¥ä½ä¸ºå¼æ¥ä½¿ç¨ãèªç¶å°ï¼è¿æå³çå®ä»¬æç±»åãä¾å¦ï¼
fn city_population_descending(city: &City) -> i64 {
-city.population
}
2
3
è¿ä¸ªå½æ°æ¥åä¸ä¸ªåæ°ï¼&Cityï¼å¹¶è¿åä¸ä¸ªi64ãå®çç±»åæ¯fn(&City) -> i64ã
ä½ å¯ä»¥å¯¹å½æ°è¿è¡ä¸å ¶ä»å¼ç¸åçæä½ãä½ å¯ä»¥å°å®ä»¬åå¨å¨åéä¸ãä½ å¯ä»¥ä½¿ç¨ææå¸¸è§çRustè¯æ³æ¥è®¡ç®å½æ°å¼ï¼
let my_key_fn: fn(&City) -> i64 =
if user.prefs.by_population {
city_population_descending
} else {
city_monster_attack_risk_descending
};
cities.sort_by_key(my_key_fn);
2
3
4
5
6
7
ç»æä½å¯ä»¥æå½æ°ç±»åçåæ®µãåVecè¿æ ·çæ³åç±»åå¯ä»¥åå¨å¤§é彿°ï¼åªè¦å®ä»¬é½å
·æç¸åçfnç±»åãèä¸å½æ°å¼å ç¨ç©ºé´å¾å°ï¼ä¸ä¸ªfn弿¯å½æ°æºå¨ç çå
åå°åï¼å°±åC++ä¸ç彿°æé䏿 ·ã
ä¸ä¸ªå½æ°å¯ä»¥æ¥åå¦ä¸ä¸ªå½æ°ä½ä¸ºåæ°ãä¾å¦ï¼
/// ç»å®ä¸ä¸ªåå¸å表åä¸ä¸ªæµè¯å½æ°ï¼è¿åéè¿æµè¯çå叿°éã
fn count_selected_cities(cities: &Vec<City>, test_fn: fn(&City) -> bool) -> usize {
let mut count = 0;
for city in cities {
if test_fn(city) {
count += 1;
}
}
count
}
/// ä¸ä¸ªæµè¯å½æ°ç示ä¾ã注æè¿ä¸ªå½æ°çç±»åæ¯`fn(&City) -> bool`ï¼ä¸`count_selected_cities`ç`test_fn`åæ°ç±»åç¸åã
fn has_monster_attacks(city: &City) -> bool {
city.monster_attack_risk > 0.0
}
// æå¤å°ä¸ªå叿æªç©è¢å»çé£é©ï¼
let n = count_selected_cities(&my_cities, has_monster_attacks);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
å¦æä½ çæC/C++ä¸ç彿°æéï¼ä½ ä¼åç°Rustç彿°å¼ä¸ä¹å®å ¨ç¸åã
äºè§£äºè¿äºä¹åï¼ä½ å¯è½ä¼æè®¶å°åç°éå çç±»åä¸å½æ°å¹¶ä¸ç¸åï¼
let limit = preferences.acceptable_monster_risk();
let n = count_selected_cities(
&my_cities,
|city| city.monster_attack_risk > limit); // é误ï¼ç±»åä¸å¹é
2
3
4
第äºä¸ªåæ°å¯¼è´äºç±»åé误ãä¸ºäºæ¯æéå ï¼æä»¬å¿ é¡»æ´æ¹è¿ä¸ªå½æ°çç±»åç¾åãå®éè¦å¦ä¸æç¤ºï¼
fn count_selected_cities<F>(cities: &Vec<City>, test_fn: F) -> usize
where
F: Fn(&City) -> bool
{
let mut count = 0;
for city in cities {
if test_fn(city) {
count += 1;
}
}
count
}
2
3
4
5
6
7
8
9
10
11
12
æä»¬åªæ´æ¹äºcount_selected_citiesçç±»åç¾åï¼èæ²¡ææ´æ¹å
¶å½æ°ä½ãæ°çæ¬æ¯æ³åçã宿¥åä»»ä½ç±»å为Fçtest_fnï¼åªè¦Få®ç°äºç¹æ®ç¹æ§Fn(&City) -> boolãæææ¥åå个&Cityä½ä¸ºåæ°å¹¶è¿åå¸å°å¼ç彿°å大夿°éå
é½ä¼èªå¨å®ç°è¿ä¸ªç¹æ§ï¼
fn(&City) -> bool // fnç±»åï¼ä»
彿°ï¼
Fn(&City) -> bool // Fnç¹æ§ï¼å½æ°åéå
é½éç¨ï¼
2
è¿ç§ç¹æ®è¯æ³æ¯å
ç½®å¨è¯è¨ä¸çã->åè¿åç±»åæ¯å¯éçï¼å¦æçç¥ï¼è¿åç±»å为()ã
æ°çæ¬çcount_selected_citiesæ¢æ¥å彿°ä¹æ¥åéå
ï¼
count_selected_cities(
&my_cities,
has_monster_attacks); // æ£å¸¸
count_selected_cities(
&my_cities,
|city| city.monster_attack_risk > limit); // 乿£å¸¸
2
3
4
5
6
为ä»ä¹æä»¬çç¬¬ä¸æ¬¡å°è¯ä¸èµ·ä½ç¨å¢ï¼å¯ï¼éå
æ¯å¯è°ç¨çï¼ä½å®ä¸æ¯fnç±»åãéå
|city| city.monster_attack_risk > limitæå®èªå·±çç±»åï¼ä¸æ¯fnç±»åã
å®é
ä¸ï¼ä½ ç¼åçæ¯ä¸ªéå
齿èªå·±çç±»åï¼å 为éå
å¯è½å
嫿°æ®ï¼ä»å
å«ä½ç¨ååç¨æçªåçå¼ãè¿äºæ°æ®å¯ä»¥æ¯ä»»ææ°éçåéï¼å¹¶ä¸å¯ä»¥æ¯ä»»æç±»åçç»åãæä»¥æ¯ä¸ªéå
齿ä¸ä¸ªç±ç¼è¯å¨å建ç临æ¶ç±»åï¼å
¶å¤§å°è¶³ä»¥å®¹çº³è¿äºæ°æ®ã没æä¸¤ä¸ªéå
çç±»åæ¯å®å
¨ç¸åçã使¯æ¯ä¸ªéå
é½å®ç°äºä¸ä¸ªFnç¹æ§ï¼æä»¬ç¤ºä¾ä¸çéå
å®ç°äºFn(&City) -> i64ã
ç±äºæ¯ä¸ªéå
齿èªå·±çç±»åï¼å¤çéå
ç代ç é常éè¦æ¯æ³åçï¼å°±åcount_selected_cities䏿 ·ãæ¯æ¬¡é½è¯¦ç»ååºæ³åç±»åæç¹éº»ç¦ï¼ä½è¦äºè§£è¿ç§è®¾è®¡çä¼ç¹ï¼ç»§ç»é
读就ç¥éäºã
# éå æ§è½
Rustçéå 设计å¾éå¸¸é«æï¼æ¯å½æ°æéæ´å¿«ï¼çè³å¿«å°å¨å¯¹æ§è½è¦æ±æé«ç代ç ä¸ä¹å¯ä»¥ä½¿ç¨ãå¦æä½ çæC++ä¸çlambda表达å¼ï¼ä½ ä¼åç°Rustéå åæ ·é«æä¸ç´§åï¼ä½æ´å®å ¨ã
å¨å¤§å¤æ°è¯è¨ä¸ï¼éå å¨å ä¸åé å åï¼éç¨å¨æè°åº¦ï¼å¹¶éè¿åå¾åæ¶æºå¶ç®¡çãå æ¤ï¼å建ãè°ç¨ååæ¶æ¯ä¸ªéå é½ä¼æ¶èå°éé¢å¤çCPUæ¶é´ãæ´ç³ç³çæ¯ï¼éå å¾å¾ä¼é»æ¢å èï¼inliningï¼ï¼èå èæ¯ç¼è¯å¨ç¨äºæ¶é¤å½æ°è°ç¨å¼éå¹¶å®ç°ä¸ç³»åå ¶ä»ä¼åçå ³é®ææ¯ãæ»ä½èè¨ï¼å¨è¿äºè¯è¨ä¸ï¼éå çéåº¦è¾æ ¢ï¼ä»¥è³äºå¨ç´§å¯çå é¨å¾ªç¯ä¸æå¨å»é¤éå æ¯ææä¹çã
Rustéå
没æè¿äºæ§è½ç¼ºç¹ãå®ä»¬ä¸ä¾èµåå¾åæ¶ãä¸Rustä¸çå
¶ä»å
容䏿 ·ï¼é¤éå°å®ä»¬æ¾å
¥BoxãVecæå
¶ä»å®¹å¨ä¸ï¼å¦åå®ä»¬ä¸ä¼å¨å ä¸åé
å
åãèä¸ï¼ç±äºæ¯ä¸ªéå
齿ç¬ç¹çç±»åï¼åªè¦Rustç¼è¯å¨ç¥éä½ æ£å¨è°ç¨çéå
çç±»åï¼å®å°±å¯ä»¥å°è¯¥ç¹å®éå
ç代ç å
èãè¿ä½¿å¾å¨ç´§å¯å¾ªç¯ä¸ä½¿ç¨éå
æ¯å¯è¡çï¼Rustç¨åºä¹ç»å¸¸è¿æ ·åï¼ä½ å°å¨ç¬¬15ç« ä¸çå°ã
å¾14-1å±ç¤ºäºRustéå
å¨å
åä¸çå¸å±ãå¨å¾çé¡¶é¨ï¼æä»¬å±ç¤ºäºéå
å°å¼ç¨çå 个å±é¨åéï¼ä¸ä¸ªå符串foodåä¸ä¸ªç®åçæä¸¾weatherï¼å
¶æ°å¼æ°å¥½ä¸º27ã
å¾14-1 éå
å¨å
åä¸çå¸å±
éå (a)使ç¨äºè¿ä¸¤ä¸ªåéãæ¾ç¶ï¼æä»¬å¨å¯»æ¾æ¢ä¾åºçç±³å·åæé¾å·é£çåå¸ãå¨å åä¸ï¼è¿ä¸ªéå çèµ·æ¥åä¸ä¸ªå°ç»æä½ï¼å å«å¯¹å®ä½¿ç¨çåéçå¼ç¨ã
请注æï¼å®ä¸å 嫿åå ¶ä»£ç çæéï¼è¿æ²¡æå¿ è¦ï¼åªè¦Rustç¥ééå çç±»åï¼å®å°±ç¥éå¨è°ç¨éå æ¶åºè¯¥è¿è¡åªæ®µä»£ç ã
éå
(b)å®å
¨ç¸åï¼åªæ¯å®æ¯ä¸ä¸ªmoveéå
ï¼æä»¥å®å
å«ç弿¯åéæ¬èº«è䏿¯å¼ç¨ã
éå (c)ä¸ä½¿ç¨å ¶ç¯å¢ä¸çä»»ä½åéãè¿ä¸ªç»æä½æ¯ç©ºçï¼æä»¥è¿ä¸ªéå æ ¹æ¬ä¸å ç¨ä»»ä½å åã
å¦å¾æç¤ºï¼è¿äºéå å ç¨ç空é´ä¸å¤§ãä½å¨å®é ä¸ï¼å³ä½¿æ¯è¿å 个åèä¹å¹¶éæ»æ¯å¿ éçãé常ï¼ç¼è¯å¨å¯ä»¥å°å¯¹éå çææè°ç¨å èï¼ç¶åçè³å¾ä¸æç¤ºçå°ç»æä½ä¹ä¼è¢«ä¼åæã
å¨ âåè°å½æ°â ä¸ï¼æä»¬å°å±ç¤ºå¦ä½å¨å ä¸åé éå 并使ç¨ç¹æ§å¯¹è±¡å¨æè°ç¨å®ä»¬ãè¿æ ·åä¼ç¨å¾®æ ¢ä¸äºï¼ä½ä»ç¶ä¸å ¶ä»ç¹æ§å¯¹è±¡æ¹æ³ä¸æ ·å¿«ã
# éå ä¸å®å ¨æ§
å°ç®å为æ¢ï¼å¨æ¬ç« ä¸æä»¬è®¨è®ºäºRustå¦ä½ç¡®ä¿éå å¨ä»å¨å´ä»£ç åç¨æç§»å¨åéæ¶éµå®è¯è¨çå®å ¨è§åãä½è¿æä¸äºä¸å¤ªææ¾çå½±åã卿¬èä¸ï¼æä»¬å°è¿ä¸æ¥è§£éå½éå ä¸¢å¼æä¿®æ¹æè·ç弿¶ä¼åçä»ä¹ã
# ä¼éæ¾å¼çéå
æä»¬å·²ç»è§è¯è¿åç¨å¼çéå åçªåå¼çéå ï¼åºç°ä¼å¯¼è´å¼è¢«éæ¾çéå åªæ¯æ¶é´é®é¢ã
å½ç¶ï¼âéæ¾ï¼killï¼â 并䏿¯ä¸ä¸ªåç¡®çæ¯è¯ãå¨Rustä¸ï¼æä»¬ä½¿ç¨dropæ¥éæ¾å¼ãæç´æ¥çæ¹æ³æ¯è°ç¨drop()ï¼
let my_str = "hello".to_string();
let f = || drop(my_str);
2
å½è°ç¨fæ¶ï¼my_strä¼è¢«éæ¾ãé£ä¹å¦ææä»¬è°ç¨å®ä¸¤æ¬¡ä¼åçä»ä¹å¢ï¼
f();
f();
2
让æä»¬ä»ç»æèä¸ä¸ãç¬¬ä¸æ¬¡è°ç¨fæ¶ï¼å®éæ¾äºmy_strï¼è¿æå³çåå¨å符串çå
åè¢«éæ¾å¹¶è¿åç»ç³»ç»ãç¬¬äºæ¬¡è°ç¨fæ¶ï¼åæ ·çäºæ
ä¼å次åçãè¿æ¯ä¸ä¸ªåééæ¾ï¼double freeï¼ï¼æ¯C++ç¼ç¨ä¸çç»å
¸é误ï¼ä¼å¼åæªå®ä¹è¡ä¸ºã
å¨Rustä¸ï¼ä¸¤æ¬¡éæ¾ä¸ä¸ªStringåæ ·æ¯ä¸ªå主æã幸è¿çæ¯ï¼Rustä¸ä¼è¿ä¹å®¹æè¢«æ¬ºéªï¼
f(); // æ£å¸¸
f(); // é误ï¼ä½¿ç¨å·²ç§»å¨çå¼
2
Rustç¥éè¿ä¸ªéå ä¸è½è¢«è°ç¨ä¸¤æ¬¡ã
ä¸ä¸ªåªè½è¢«è°ç¨ä¸æ¬¡çéå å¯è½çèµ·æ¥å¾ä¸å¯»å¸¸ï¼ä½å¨æ¬ä¹¦ä¸æä»¬ä¸ç´å¨è®¨è®ºæææåçå½å¨æãå¼è¢«æ¶èï¼å³è¢«ç§»å¨ï¼çæ¦å¿µæ¯Rustçæ ¸å¿æ¦å¿µä¹ä¸ãéå å¨è¿æ¹é¢ä¸å ¶ä»å 容çåçæ¯ä¸æ ·çã
# FnOnce
让æä»¬åè¯ä¸æ¬¡ï¼çè½å¦è®©Rustä¸¤æ¬¡éæ¾ä¸ä¸ªStringãè¿æ¬¡ï¼æä»¬ä½¿ç¨è¿ä¸ªæ³å彿°ï¼
fn call_twice<F>(closure: F)
where
F: Fn()
{
closure();
closure();
}
2
3
4
5
6
7
è¿ä¸ªæ³å彿°å¯ä»¥æ¥åä»»ä½å®ç°äºFn()ç¹æ§çéå
ï¼å³ä¸å¸¦åæ°ä¸è¿åå¼ä¸º()çéå
ï¼ä¸å½æ°ä¸æ ·ï¼å¦æè¿åç±»åæ¯()ï¼åå¯ä»¥çç¥ï¼Fn()æ¯Fn() -> ()çç®åï¼ã
ç°å¨ï¼å¦ææä»¬å°è¿ä¸ªä¸å®å ¨çéå ä¼ éç»è¿ä¸ªæ³å彿°ä¼åçä»ä¹å¢ï¼
let my_str = "hello".to_string();
let f = || drop(my_str);
call_twice(f);
2
3
åæ ·ï¼éå
å¨è¢«è°ç¨æ¶ä¼éæ¾my_strãè°ç¨ä¸¤æ¬¡å°±ä¼å¯¼è´åééæ¾ãä½Rust忬¡æ²¡æè¢«æ¬ºéªï¼
error[E0525]: expected a closure that implements the `Fn` trait,
but
this closure only implements `FnOnce`
--> closures_twice.rs:12:13
|
8 | let f = || drop(my_str);
| ^^^^^^^^------^
| | |
| | closure is `FnOnce` because it moves the
variable `my_str`
| | out of its environment
| this closure implements `FnOnce`, not `Fn`
9 | call_twice(f);
| ---------- the requirement to implement `Fn` derives from
here
2
3
4
5
6
7
8
9
10
11
12
13
14
15
è¿ä¸ªé误信æ¯è®©æä»¬å¯¹Rustå¦ä½å¤ç âä¼éæ¾å¼çéå
â æäºæ´å¤äºè§£ãå®ä»¬æ¬å¯ä»¥è¢«å®å
¨ç¦æ¢å¨è¯è¨ä¸ä½¿ç¨ï¼ä½æ¸
çéå
ææ¶å¾æç¨ãå æ¤ï¼Rustéå¶äºå®ä»¬ç使ç¨ãåfè¿æ ·ä¼éæ¾å¼çéå
ä¸å
è®¸æ¥æFnç¹æ§ãä»åé¢ä¸çï¼å®ä»¬æ ¹æ¬ä¸æ¯Fnãå®ä»¬å®ç°äºä¸ä¸ªåè½è¾å¼±çç¹æ§FnOnceï¼å³åªè½è¢«è°ç¨ä¸æ¬¡çéå
çç¹æ§ã
ç¬¬ä¸æ¬¡è°ç¨FnOnceéå
æ¶ï¼éå
æ¬èº«å°±ä¼è¢«æ¶èæã就好åFnåFnOnceè¿ä¸¤ä¸ªç¹æ§æ¯è¿æ ·å®ä¹çï¼
// æ åæ°ç`Fn`å`FnOnce`ç¹æ§ç伪代ç
trait Fn() -> R {
fn call(&self) -> R;
}
trait FnOnce() -> R {
fn call_once(self) -> R;
}
2
3
4
5
6
7
8
å°±åç®æ¯è¡¨è¾¾å¼a + bæ¯æ¹æ³è°ç¨Add::add(a, b)çç®å䏿 ·ï¼Rustå°closure()è§ä¸ºåé¢ç¤ºä¾ä¸ä¸¤ä¸ªç¹æ§æ¹æ³ä¹ä¸çç®åã对äºFnéå
ï¼closure()å±å¼ä¸ºclosure.call()ãè¿ä¸ªæ¹æ³éè¿å¼ç¨è·åselfï¼æä»¥éå
ä¸ä¼è¢«ç§»å¨ã使¯ï¼å¦æéå
åªå®å
¨å°è°ç¨ä¸æ¬¡ï¼é£ä¹closure()ä¼å±å¼ä¸ºclosure.call_once()ãè¿ä¸ªæ¹æ³æå¼è·åselfï¼æä»¥éå
ä¼è¢«æ¶èæã
å½ç¶ï¼æä»¬å¨è¿éæ
æä½¿ç¨drop()æ¥å¶é 麻ç¦ãå¨å®è·µä¸ï¼ä½ 大夿¯æå¤é·å
¥è¿ç§æ
åµãè¿ç§æ
åµå¹¶ä¸ç»å¸¸åçï¼ä½å¶å°ä½ ä¼ç¼åä¸äºéå
代ç ï¼æ æä¸æ¶èäºä¸ä¸ªå¼ï¼
let dict = produce_glossary();
let debug_dump_dict = || {
for (key, value) in dict { // ååï¼
println!("{:?} - {:?}", key, value);
}
};
2
3
4
5
6
ç¶åï¼å½ä½ 夿¬¡è°ç¨debug_dump_dict()æ¶ï¼ä½ ä¼å¾å°è¿æ ·çé误信æ¯ï¼
error[E0382]: use of moved value: `debug_dump_dict`
--> closures_debug_dump_dict.rs:18:5
|
19 | debug_dump_dict();
| ----------------- `debug_dump_dict` moved due to this
call
20 | debug_dump_dict();
| ^^^^^^^^^^^^^^^ value used here after move
|
note: closure cannot be invoked more than once because it moves
the variable
`dict` out of its environment
--> src/main.rs:13:29
|
13 | for (key, value) in dict {
| ^^^^
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
为äºè°è¯è¿ä¸ªé®é¢ï¼æä»¬å¿
须弿¸
æ¥ä¸ºä»ä¹è¿ä¸ªéå
æ¯FnOnceãè¿éæ£å¨è¢«æ¶èç弿¯åªä¸ªå¢ï¼ç¼è¯å¨å¾è´´å¿å°æåºæ¯dictï¼å¨è¿ç§æ
åµä¸å®æ¯æä»¬å¯ä¸å¼ç¨çåéãåï¼é®é¢åºå¨è¿éï¼æä»¬ç´æ¥è¿ä»£dictï¼ä»èæ¶èäºå®ãæä»¬åºè¯¥è¿ä»£&dictï¼è䏿¯ç´æ¥è¿ä»£dictï¼è¿æ ·æè½éè¿å¼ç¨è®¿é®å¼ï¼
let debug_dump_dict = || {
for (key, value) in &dict { // ä¸ä¼æ¶èdict
println!("{:?} - {:?}", key, value);
}
};
2
3
4
5
è¿æ ·å°±ä¿®å¤äºé误ï¼è¿ä¸ªå½æ°ç°å¨æ¯ä¸ä¸ªFnéå
ï¼å¯ä»¥è¢«è°ç¨ä»»ææ¬¡æ°ã
# FnMut
è¿æä¸ç§éå ï¼å³å å«å¯åæ°æ®æå¯åå¼ç¨çéå ã
Rust认为ä¸å¯åçå¼å¯ä»¥å¨å¤ä¸ªçº¿ç¨ä¹é´å®å ¨å ±äº«ã使¯ï¼å ±äº«å å«å¯åæ°æ®çä¸å¯åéå æ¯ä¸å®å ¨çï¼ä»å¤ä¸ªçº¿ç¨è°ç¨è¿æ ·çéå å¯è½ä¼å¯¼è´åç§ç«ææ¡ä»¶ï¼å 为å¤ä¸ªçº¿ç¨å¯è½ä¼åæ¶å°è¯è¯»åç¸åçæ°æ®ã
å æ¤ï¼Rustè¿æä¸ç±»éå
ï¼å³FnMutï¼è¿æ¯ç¨äºå¯åæä½çéå
ç±»å«ãFnMutéå
éè¿å¯åå¼ç¨è°ç¨ï¼å°±å¥½åå®ä»¬æ¯è¿æ ·å®ä¹çï¼
// `Fn`ã`FnMut`å`FnOnce`ç¹æ§ç伪代ç
trait Fn() -> R {
fn call(&self) -> R;
}
trait FnMut() -> R {
fn call_mut(&mut self) -> R;
}
trait FnOnce() -> R {
fn call_once(self) -> R;
}
2
3
4
5
6
7
8
9
10
11
12
ä»»ä½éè¦å¯¹å¼è¿è¡å¯å访é®ä½ä¸ä¼éæ¾ä»»ä½å¼çéå
齿¯FnMutéå
ãä¾å¦ï¼
let mut i = 0;
let incr = || {
i += 1; // incråç¨äºå¯¹içå¯åå¼ç¨
println!("Ding! i is now: {}", i);
};
call_twice(incr);
2
3
4
5
6
æç
§æä»¬ä¹åç¼åçcall_twice彿°ï¼å®éè¦ä¸ä¸ªFnéå
ãç±äºincræ¯FnMutéå
è䏿¯Fnéå
ï¼è¿æ®µä»£ç æ æ³ç¼è¯ã
ä¸è¿ï¼æä¸ä¸ªç®åçè§£å³æ¹æ³ã为äºçè§£è¿ä¸ªè§£å³æ¹æ³ï¼è®©æä»¬å顾ä¸ä¸å¹¶æ»ç»ä½ æå¦çå ³äºRustéå çä¸ç±»ã
Fnæ¯ä¸ç±»éå å彿°ï¼ä½ å¯ä»¥ä¸åéå¶å°å¤æ¬¡è°ç¨å®ä»¬ãè¿ä¸ªæé«çº§å«çç±»å«è¿å æ¬ææfn彿°ãFnMutæ¯ä¸ç±»éå ï¼å¦æéå æ¬èº«è¢«å£°æä¸ºå¯åçï¼å°±å¯ä»¥å¤æ¬¡è°ç¨ãFnOnceæ¯ä¸ç±»éå ï¼å¦æè°ç¨è æ¥æè¯¥éå ï¼å°±å¯ä»¥è°ç¨ä¸æ¬¡ã
æ¯ä¸ªFnéå
齿»¡è¶³FnMutçè¦æ±ï¼æ¯ä¸ªFnMutéå
齿»¡è¶³FnOnceçè¦æ±ãå¦å¾14-2æç¤ºï¼å®ä»¬ä¸æ¯ä¸ä¸ªç¬ç«çç±»å«ãç¸åï¼Fn()æ¯FnMut()çåç¹æ§ï¼èFnMut()æ¯FnOnce()çåç¹æ§ãè¿ä½¿å¾Fnæä¸ºæå
·æä»æ§ä¸åè½æå¼ºå¤§çç±»å«ãFnMutåFnOnceæ¯æ´å®½æ³çç±»å«ï¼å
æ¬ä½¿ç¨ä¸æéå¶çéå
ã
å¾14-2 ä¸ç±»éå
çç»´æ©å¾
ç°å¨æä»¬å·²ç»æ¢³çæ¸
æ¥äºè¿äºç¥è¯ï¼å¾ææ¾ï¼ä¸ºäºæ¥åå°½å¯è½å¹¿æ³çéå
ï¼æä»¬çcall_twice彿°å®é
ä¸åºè¯¥æ¥åææFnMutéå
ï¼å¦ä¸æç¤ºï¼
fn call_twice<F>(mut closure: F)
where
F: FnMut()
{
closure();
closure();
}
2
3
4
5
6
7
第ä¸è¡ç约æä»F: Fn()å为äºF: FnMut()ãéè¿è¿ä¸ªæ´æ¹ï¼æä»¬ä»ç¶å¯ä»¥æ¥åææFnéå
ï¼å¹¶ä¸è¿å¯ä»¥å¯¹ä¼ä¿®æ¹åéçéå
使ç¨call_twiceï¼
let mut i = 0;
call_twice(|| i += 1); // æ£å¸¸ï¼
assert_eq!(i, 2);
2
3
# éå çCopyåClone
å°±åRustä¼èªå¨å¤æåªäºéå
åªè½è¢«è°ç¨ä¸æ¬¡ä¸æ ·ï¼å®ä¹å¯ä»¥å¤æåªäºéå
å¯ä»¥å®ç°CopyåCloneï¼åªäºä¸è½ã
æ£å¦æä»¬åé¢è§£éçï¼éå
è¢«è¡¨ç¤ºä¸ºç»æä½ï¼å
¶ä¸å
å«å®ä»¬æè·çåéçå¼ï¼å¯¹äºmoveéå
ï¼æå¼ç¨ï¼å¯¹äºémoveéå
ï¼ãéå
ä¸çCopyåCloneè§å䏿®éç»æä½çCopyåCloneè§åç¸åãä¸ä¸ªä¸ä¿®æ¹åéçémoveéå
åªææå
±äº«å¼ç¨ï¼èå
±äº«å¼ç¨æ¢æ¯Clone忝Copyçï¼æä»¥è¿æ ·çéå
乿¯CloneåCopyçï¼
let y = 10;
let add_y = |x| x + y;
let copy_of_add_y = add_y; // è¿ä¸ªéå
æ¯`Copy`çï¼æä»¥...
assert_eq!(add_y(copy_of_add_y(22)), 42); // ...æä»¬å¯ä»¥è°ç¨è¿ä¸¤ä¸ªéå
2
3
4
å¦ä¸æ¹é¢ï¼ä¸ä¸ªä¼ä¿®æ¹åéçémoveéå
å¨å
¶å
é¨è¡¨ç¤ºä¸å
å«å¯åå¼ç¨ãå¯åå¼ç¨æ¢ä¸æ¯Cloneä¹ä¸æ¯Copyçï¼æä»¥ä½¿ç¨å¯åå¼ç¨çéå
ä¹ä¸æ¯CloneåCopyçï¼
let mut x = 0;
let mut add_to_x = |n| { x += n; x };
let copy_of_add_to_x = add_to_x; // è¿æ¯ç§»å¨ï¼è䏿¯å¤å¶
assert_eq!(add_to_x(copy_of_add_to_x(1)), 2); // é误ï¼ä½¿ç¨å·²ç§»å¨çå¼
2
3
4
对äºmoveéå
ï¼è§åæ´ç®åã妿moveéå
æè·çææå
容齿¯Copyçï¼é£ä¹å®å°±æ¯Copyçã妿宿è·çææå
容齿¯Cloneçï¼é£ä¹å®å°±æ¯Cloneçãä¾å¦ï¼
let mut greeting = String::from("Hello, ");
let greet = move |name| {
greeting.push_str(name);
println!("{}", greeting);
};
greet.clone()("Alfred");
greet.clone()("Bruce");
2
3
4
5
6
7
è¿ç§.clone()(...)è¯æ³æç¹å¥æªï¼ä½å®åªæ¯è¡¨ç¤ºæä»¬å
ééå
ï¼ç¶åè°ç¨å
éçéå
ãè¿ä¸ªç¨åºçè¾åºæ¯ï¼
Hello, Alfred
Hello, Bruce
2
å½greetingå¨greetä¸è¢«ä½¿ç¨æ¶ï¼å®è¢«ç§»å¨å°äºå
é¨è¡¨ç¤ºgreetçç»æä½ä¸ï¼å ä¸ºè¿æ¯ä¸ä¸ªmoveéå
ãæä»¥ï¼å½æä»¬å
égreetæ¶ï¼å®å
é¨çææå
容ä¹ä¼è¢«å
éãæä¸¤ä¸ªgreetingç坿¬ï¼å¨è°ç¨greetçå
éæ¶ä¼åå«è¢«ä¿®æ¹ãè¿æ¬èº«å¯è½ç¨å¤ä¸å¤§ï¼ä½å½ä½ éè¦å°åä¸ä¸ªéå
ä¼ éç»å¤ä¸ªå½æ°æ¶ï¼å®ä¼é常æå¸®å©ã
# åè°å½æ°
许å¤åºå°åè°å½æ°ä½ä¸ºå
¶APIçä¸é¨åï¼ç¨æ·æä¾å½æ°ï¼ä¾åºå¨ä¹åè°ç¨ãå®é
ä¸ï¼å¨æ¬ä¹¦ä¸ä½ å·²ç»è§è¿ä¸äºè¿æ ·çAPIãå¨ç¬¬2ç« ä¸ï¼æä»¬ä½¿ç¨actix-webæ¡æ¶ç¼åäºä¸ä¸ªç®åçWebæå¡å¨ã该ç¨åºçä¸ä¸ªéè¦é¨åæ¯è·¯ç±å¨ï¼å¦ä¸æç¤ºï¼
App::new()
.route("/", web::get().to(get_index))
.route("/gcd", web::post().to(post_gcd))
2
3
è·¯ç±å¨çä½ç¨æ¯å°æ¥èªäºèç½çä¼ å
¥è¯·æ±è·¯ç±å°å¤çç¹å®ç±»å请æ±çRust代ç é¨åãå¨è¿ä¸ªä¾åä¸ï¼get_indexåpost_gcdæ¯æä»¬å¨ç¨åºå
¶ä»å°æ¹ä½¿ç¨fnå
³é®å声æç彿°åã使们ä¹å¯ä»¥ä¼ ééå
ï¼å¦ä¸æç¤ºï¼
App::new()
.route("/", web::get().to(|| {
HttpResponse::Ok()
.content_type("text/html")
.body("<title>GCD Calculator</title>...")
}))
.route("/gcd", web::post().to(|form: web::Form<GcdParameters>| {
HttpResponse::Ok()
.content_type("text/html")
.body(format!("The GCD of {} and {} is {}.", form.n, form.m, gcd(form.n, form.m)))
}))
2
3
4
5
6
7
8
9
10
11
è¿æ¯å 为actix-web被ç¼å为æ¥åä»»ä½çº¿ç¨å®å
¨çFnä½ä¸ºåæ°ã
æä»¬å¨èªå·±çç¨åºä¸å¦ä½åå°è¿ä¸ç¹å¢ï¼è®©æä»¬å°è¯ä»å¤´å¼å§ç¼åä¸ä¸ªé常ç®åçè·¯ç±å¨ï¼ä¸ä½¿ç¨actix-webä¸çä»»ä½ä»£ç ãæä»¬å¯ä»¥å
声æä¸äºç±»åæ¥è¡¨ç¤ºHTTP请æ±åååºï¼
struct Request {
method: String,
url: String,
headers: HashMap<String, String>,
body: Vec<u8>
}
struct Response {
code: u32,
headers: HashMap<String, String>,
body: Vec<u8>
}
2
3
4
5
6
7
8
9
10
11
12
ç°å¨ï¼è·¯ç±å¨çå·¥ä½å°±æ¯ç®åå°åå¨ä¸ä¸ªå°URLæ å°å°åè°å½æ°ç表ï¼ä»¥ä¾¿æéè°ç¨æ£ç¡®çåè°å½æ°ãï¼ä¸ºç®åèµ·è§ï¼æä»¬åªå è®¸ç¨æ·å建ä¸å个精确URLå¹é çè·¯ç±ãï¼
struct BasicRouter<C>
where
C: Fn(&Request) -> Response
{
routes: HashMap<String, C>
}
impl<C> BasicRouter<C>
where
C: Fn(&Request) -> Response
{
/// å建ä¸ä¸ªç©ºè·¯ç±å¨ã
fn new() -> BasicRouter<C> {
BasicRouter { routes: HashMap::new() }
}
/// åè·¯ç±å¨æ·»å 䏿¡è·¯ç±ã
fn add_route(&mut self, url: &str, callback: C) {
self.routes.insert(url.to_string(), callback);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ä¸å¹¸çæ¯ï¼æä»¬ç¯äºä¸ä¸ªé误ãä½ æ³¨æå°äºåï¼
åªè¦æä»¬åªåè¿ä¸ªè·¯ç±å¨æ·»å 䏿¡è·¯ç±ï¼å®å°±è½æ£å¸¸å·¥ä½ï¼
let mut router = BasicRouter::new();
router.add_route("/", |_| get_form_response());
2
è¿æ®µä»£ç å¯ä»¥ç¼è¯å¹¶è¿è¡ãä½ä¸å¹¸çæ¯ï¼å¦ææä»¬åæ·»å 䏿¡è·¯ç±ï¼
router.add_route("/gcd", |req| get_gcd_response(req));
å°±ä¼å¾å°é误ï¼
error[E0308]: mismatched types
--> closures_bad_router.rs:41:30
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
41 | router.add_route("/gcd", |req| get_gcd_response(req));
| expected closure, found a different closure
|
= note: expected type `[closure@closures_bad_router.rs:40:27: 40:50]`
found type `[closure@closures_bad_router.rs:41:30: 41:57]`
note: no two closures, even if identical, have the same type
help: consider boxing your closure and/or using it as a trait object
2
3
4
5
6
7
8
9
10
11
æä»¬çé误å¨äºå®ä¹BasicRouterç±»åçæ¹å¼ï¼
struct BasicRouter<C>
where
C: Fn(&Request) -> Response
{
routes: HashMap<String, C>
}
2
3
4
5
6
æä»¬æ æä¸å£°æäºæ¯ä¸ªBasicRouter齿ä¸ä¸ªåä¸çåè°ç±»åCï¼å¹¶ä¸HashMapä¸çææåè°é½æ¯è¯¥ç±»åãå¨ â该使ç¨åªç§æ¹å¼â ä¸ï¼æä»¬å±ç¤ºäºä¸ä¸ªSaladç±»åï¼å®ä¹æåæ ·çé®é¢ï¼
struct Salad<V: Vegetable> {
veggies: Vec<V>
}
2
3
è¿éçè§£å³æ¹æ¡ä¸Saladç䏿 ·ï¼ç±äºæä»¬å¸ææ¯æå¤ç§ç±»åï¼æä»¥éè¦ä½¿ç¨è£
ç®±åç¹æ§å¯¹è±¡ï¼
type BoxedCallback = Box<dyn Fn(&Request) -> Response>;
struct BasicRouter {
routes: HashMap<String, BoxedCallback>
}
2
3
4
æ¯ä¸ªè£
ç®±åçéå
å¯ä»¥å
å«ä¸åç±»åçéå
ï¼æä»¥å个HashMapå¯ä»¥å
å«åç§åè°å½æ°ã注æï¼ç±»ååæ°Cå·²ç»ä¸åå¨äºã
è¿éè¦å¯¹æ¹æ³è¿è¡ä¸äºè°æ´ï¼
impl BasicRouter {
// å建ä¸ä¸ªç©ºè·¯ç±å¨ã
fn new() -> BasicRouter {
BasicRouter { routes: HashMap::new() }
}
// åè·¯ç±å¨æ·»å 䏿¡è·¯ç±ã
fn add_route<C>(&mut self, url: &str, callback: C)
where
C: Fn(&Request) -> Response + 'static
{
self.routes.insert(url.to_string(), Box::new(callback));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
注æï¼
add_routeç±»åç¾åä¸Cç两个约æï¼ä¸ä¸ªç¹å®çFnç¹æ§å'staticçå½å¨æãRustè¦æ±æä»¬æ·»å è¿ä¸ª'static约æã没æå®ï¼å¯¹Box::new(callback)çè°ç¨å°æ¯ä¸ä¸ªé误ï¼å ä¸ºå¦æéå å å«å¯¹å³å°è¶ åºä½ç¨åçåéçåç¨å¼ç¨ï¼åå¨è¯¥éå æ¯ä¸å®å ¨çã
æåï¼æä»¬ç®åçè·¯ç±å¨åå¤å¥½å¤çä¼ å ¥ç请æ±äºï¼
impl BasicRouter {
fn handle_request(&self, request: &Request) -> Response {
match self.routes.get(&request.url) {
None => not_found_response(),
Some(callback) => callback(request)
}
}
}
2
3
4
5
6
7
8
å¨çºç²ä¸äºçµæ´»æ§çæ
åµä¸ï¼æä»¬è¿å¯ä»¥ç¼åä¸ä¸ªæ´èç空é´çè·¯ç±å¨çæ¬ï¼å®ä¸åå¨ç¹æ§å¯¹è±¡ï¼èæ¯ä½¿ç¨å½æ°æéï¼å³fnç±»åãè¿äºç±»åï¼å¦fn(u32) -> u32ï¼ä¸éå
çè¡ä¸ºå¾ç¸ä¼¼ï¼
fn add_ten(x: u32) -> u32 {
x + 10
}
let fn_ptr: fn(u32) -> u32 = add_ten;
let eleven = fn_ptr(1); // 11
2
3
4
5
6
å®é
ä¸ï¼ä¸æè·ç¯å¢ä¸ä»»ä½å
容çéå
ä¸å½æ°æéæ¯ç¸åçï¼å 为å®ä»¬ä¸éè¦ä¿åå
³äºæè·åéçä»»ä½é¢å¤ä¿¡æ¯ãå¦æä½ å¨ç»å®æå½æ°ç¾å䏿å®äºåéçfnç±»åï¼ç¼è¯å¨ä¼å¾ä¹æè®©ä½ 以è¿ç§æ¹å¼ä½¿ç¨å®ä»¬ï¼
let closure_ptr: fn(u32) -> u32 = |x| x + 1;
let two = closure_ptr(1); // 2
2
䏿è·åéçéå
ä¸åï¼è¿äºå½æ°æéåªå ç¨ä¸ä¸ªusize大å°ç空é´ã
彿°æéä¹å¯ä»¥ç¨äºå®ç°æä»¬èªå·±ç卿è°åº¦ï¼è䏿¯å使ç¨Box<dyn Fn()>飿 ·ä¾èµç¼è¯å¨ï¼
struct FnPointerRouter {
routes: HashMap<String, fn(&Request) -> Response>
}
2
3
è¿éï¼HashMap为æ¯ä¸ªStringåªåå¨ä¸ä¸ªusizeï¼å
³é®æ¯æ²¡æBoxãé¤äºHashMapæ¬èº«ï¼æ ¹æ¬æ²¡æå¨æåé
ãå½ç¶ï¼æ¹æ³ä¹éè¦è°æ´ï¼
impl FnPointerRouter {
// å建ä¸ä¸ªç©ºè·¯ç±å¨ã
fn new() -> FnPointerRouter {
FnPointerRouter { routes: HashMap::new() }
}
// åè·¯ç±å¨æ·»å 䏿¡è·¯ç±ã
fn add_route(&mut self, url: &str, callback: fn(&Request) -> Response) {
self.routes.insert(url.to_string(), callback);
}
}
2
3
4
5
6
7
8
9
10
11
å¦å¾14-1æç¤ºï¼éå
å
·æç¬ç¹çç±»åï¼å 为æ¯ä¸ªéå
æè·ä¸åçåéï¼æä»¥é¤å
¶ä»å ç´ å¤ï¼å®ä»¬ç大å°ä¹åä¸ç¸åã使¯ï¼å¦æå®ä»¬ä¸æè·ä»»ä½å
容ï¼å°±æ²¡æä»ä¹éè¦åå¨çã卿¥ååè°å½æ°ç彿°ä¸ä½¿ç¨fnæéï¼ä½ å¯ä»¥éå¶è°ç¨è
åªä½¿ç¨è¿äºä¸æè·åéçéå
ï¼å¨ä½¿ç¨åè°å½æ°ç代ç ä¸è·å¾ä¸äºæ§è½åçµæ´»æ§ï¼åæ¶ä»¥çºç²APIç¨æ·ççµæ´»æ§ä¸ºä»£ä»·ã
# ææä½¿ç¨éå
妿们æè§ï¼Rustçéå ä¸å¤§å¤æ°å ¶ä»è¯è¨ä¸çéå ä¸åãæå¤§çåºå«å¨äºï¼å¨æåå¾åæ¶ï¼GCï¼çè¯è¨ä¸ï¼ä½ å¯ä»¥å¨éå ä¸ä½¿ç¨å±é¨åéï¼èæ éèèçå½å¨æææææé®é¢ãä½å¨æ²¡æGCçRustä¸ï¼æ åµå°±ä¸åäºãä¸äºå¨JavaãC#åJavaScriptä¸å¸¸è§ç设计模å¼ï¼å¨ä¸åä¿®æ¹çæ åµä¸æ æ³å¨Rustä¸ä½¿ç¨ã
ä¾å¦ï¼ä»¥æ¨¡å - è§å¾ - æ§å¶å¨è®¾è®¡æ¨¡å¼ï¼ç®ç§°MVCï¼ä¸ºä¾ï¼å¦å¾14-3æç¤ºã对äºç¨æ·çé¢çæ¯ä¸ªå ç´ ï¼MVCæ¡æ¶ä¼å建ä¸ä¸ªå¯¹è±¡ï¼ä¸ä¸ªè¡¨ç¤ºè¯¥UIå ç´ ç¶æçæ¨¡åï¼ä¸ä¸ªè´è´£å ¶å¤è§çè§å¾ï¼ä»¥åä¸ä¸ªå¤çç¨æ·äº¤äºçæ§å¶å¨ãå¤å¹´æ¥ï¼å·²ç»å®ç°äºæ æ°ç§MVCçåä½ï¼ä½æ»ä½æè·¯æ¯è¿ä¸ä¸ªå¯¹è±¡ä»¥æç§æ¹å¼åæ UIçèè´£ã
é®é¢å¨äºï¼é常æ¯ä¸ªå¯¹è±¡é½ç´æ¥æéè¿åè°å½æ°ææå¯¹å
¶ä»ä¸ä¸ªæä¸¤ä¸ªå¯¹è±¡çå¼ç¨ï¼å¦å¾14-3æç¤ºãæ¯å½å
¶ä¸ä¸ä¸ªå¯¹è±¡åçååæ¶ï¼å®ä¼éç¥å
¶ä»å¯¹è±¡ï¼ä»¥ä¾¿ææå
容é½è½åæ¶æ´æ°ãä½å¨è¿ç§æ¨¡å¼ä¸ï¼ä»æ¥ä¸ä¼æ¶ååªä¸ªå¯¹è±¡ âæ¥æâ å
¶ä»å¯¹è±¡çé®é¢ã
å¾14-3 模å - è§å¾ - æ§å¶å¨è®¾è®¡æ¨¡å¼
å¨Rustä¸ï¼å¦æä¸åä¸äºæ´æ¹ï¼å°±æ æ³å®ç°è¿ç§æ¨¡å¼ãå¿ é¡»æç¡®æææï¼å¹¶ä¸å¿ é¡»æ¶é¤å¼ç¨å¾ªç¯ã模ååæ§å¶å¨ä¸è½ç¸äºç´æ¥å¼ç¨ã
Rust大èå°è®¤ä¸ºå卿´å¥½çæ¿ä»£è®¾è®¡ãææ¶ï¼ä½ å¯ä»¥éè¿è®©æ¯ä¸ªéå
æ¥æ¶å
¶æéçå¼ç¨ä½ä¸ºåæ°ï¼æ¥è§£å³éå
æææåçå½å¨æçé®é¢ãææ¶ï¼ä½ å¯ä»¥ä¸ºç³»ç»ä¸çæ¯ä¸ªäºç©åé
ä¸ä¸ªç¼å·ï¼å¹¶ä¼ éè¿äºç¼å·è䏿¯å¼ç¨ãæè
ï¼ä½ å¯ä»¥å®ç°MVCçä¼å¤åä½ä¹ä¸ï¼å
¶ä¸å¯¹è±¡ä¹é´å¹¶éé½ç¸äºå¼ç¨ãæè
ï¼ä½ å¯ä»¥ä»¿ç
§å
·æååæ°æ®æµçéMVCç³»ç»ï¼å¦FacebookçFluxæ¶æï¼å¦å¾14-4æç¤ºï¼æ¥è®¾è®¡ä½ çå·¥å
·å
ã

å¾14-4 Fluxæ¶æï¼MVCçæ¿ä»£æ¹æ¡
ç®èè¨ä¹ï¼å¦æä½ è¯å¾ä½¿ç¨Rustéå æå»ºä¸ä¸ª âå¯¹è±¡çæµ·æ´âï¼ä½ å°ä¼éå°å°é¾ãä½æå ¶ä»æ¿ä»£æ¹æ¡ãå¨è¿ç§æ åµä¸ï¼è½¯ä»¶å·¥ç¨ä½ä¸ºä¸é¨å¦ç§ä¼¼ä¹å·²ç»å¾åäºè¿äºæ¿ä»£æ¹æ¡ï¼å 为å®ä»¬æ´ç®åã
å¨ä¸ä¸ç« ä¸ï¼æä»¬å°è½¬åä¸ä¸ªéå çæ£åæ¥ä¼å¿ç主é¢ãæä»¬å°ç¼åä¸ç§ä»£ç ï¼å åå©ç¨Rustéå çç®æ´ãå¿«éå髿ï¼è¿ç§ä»£ç ç¼åèµ·æ¥æè¶£ï¼æäºé 读ï¼å¹¶ä¸é常å®ç¨ãæ¥ä¸æ¥ï¼Rustè¿ä»£å¨ã