[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fdata-type":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fdata-type":1663,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fdata-type":1687},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":1659,"stem":1660,"id":1661,"extension":1662},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fdata-type","第四章：复合数据类型","结构体、枚举与集合类型是 Rust 构建复杂数据模型的核心工具。这一章你将学会如何定义自定义类型、利用模式匹配优雅地解构数据，以及选用合适的标准集合来高效组织数据。","技能小册",[12,13],"rust","data-type","2021-02-24",false,{"type":17,"value":18,"toc":1628},"minimark",[19,23,26,31,34,38,41,82,85,115,118,127,134,168,171,174,214,221,245,267,270,277,297,303,318,321,331,352,380,393,448,451,462,482,486,489,492,495,529,532,553,556,563,569,593,615,630,637,643,667,673,702,708,715,720,754,758,765,789,792,814,817,824,848,857,862,891,896,915,918,921,924,944,947,967,970,979,983,986,993,999,1019,1026,1035,1038,1057,1081,1084,1120,1125,1134,1143,1149,1169,1181,1209,1215,1235,1242,1251,1264,1270,1280,1311,1321,1336,1339,1353,1368,1373,1388,1390,1409,1412,1415,1461,1464,1468,1471,1474,1494,1523,1549,1557,1560,1624],[20,21,8],"h1",{"id":22},"第四章复合数据类型",[24,25,9],"p",{},[27,28,30],"h2",{"id":29},"_41-结构体struct","4.1 结构体（struct）",[24,32,33],{},"结构体是自定义数据类型的基本方式，可以把多个相关的值打包在一起，并为每个字段命名，让代码意涵更清晰。",[35,36,37],"h3",{"id":37},"定义与实例化",[24,39,40],{},"定义一个结构体：",[42,43,47],"pre",{"className":44,"code":45,"language":12,"meta":46,"style":46},"language-rust shiki shiki-themes material-theme-lighter github-light github-dark","struct User {\n    active: bool,\n    username: String,\n    sign_in_count: u64,\n}\n","",[48,49,50,58,64,70,76],"code",{"__ignoreMap":46},[51,52,55],"span",{"class":53,"line":54},"line",1,[51,56,57],{},"struct User {\n",[51,59,61],{"class":53,"line":60},2,[51,62,63],{},"    active: bool,\n",[51,65,67],{"class":53,"line":66},3,[51,68,69],{},"    username: String,\n",[51,71,73],{"class":53,"line":72},4,[51,74,75],{},"    sign_in_count: u64,\n",[51,77,79],{"class":53,"line":78},5,[51,80,81],{},"}\n",[24,83,84],{},"创建实例时，字段顺序不必与定义一致，但所有字段都必须赋值：",[42,86,88],{"className":44,"code":87,"language":12,"meta":46,"style":46},"let user1 = User {\n    active: true,\n    username: String::from(\"alice\"),\n    sign_in_count: 1,\n};\n",[48,89,90,95,100,105,110],{"__ignoreMap":46},[51,91,92],{"class":53,"line":54},[51,93,94],{},"let user1 = User {\n",[51,96,97],{"class":53,"line":60},[51,98,99],{},"    active: true,\n",[51,101,102],{"class":53,"line":66},[51,103,104],{},"    username: String::from(\"alice\"),\n",[51,106,107],{"class":53,"line":72},[51,108,109],{},"    sign_in_count: 1,\n",[51,111,112],{"class":53,"line":78},[51,113,114],{},"};\n",[24,116,117],{},"通过点号访问字段：",[42,119,121],{"className":44,"code":120,"language":12,"meta":46,"style":46},"println!(\"{}\", user1.username);\n",[48,122,123],{"__ignoreMap":46},[51,124,125],{"class":53,"line":54},[51,126,120],{},[24,128,129,130,133],{},"只有把整个实例声明为 ",[48,131,132],{},"mut"," 才能修改字段，Rust 不允许只将部分字段标记为可变。",[42,135,137],{"className":44,"code":136,"language":12,"meta":46,"style":46},"let mut user2 = User {\n    active: true,\n    username: String::from(\"bob\"),\n    sign_in_count: 2,\n};\nuser2.sign_in_count += 1;\n",[48,138,139,144,148,153,158,162],{"__ignoreMap":46},[51,140,141],{"class":53,"line":54},[51,142,143],{},"let mut user2 = User {\n",[51,145,146],{"class":53,"line":60},[51,147,99],{},[51,149,150],{"class":53,"line":66},[51,151,152],{},"    username: String::from(\"bob\"),\n",[51,154,155],{"class":53,"line":72},[51,156,157],{},"    sign_in_count: 2,\n",[51,159,160],{"class":53,"line":78},[51,161,114],{},[51,163,165],{"class":53,"line":164},6,[51,166,167],{},"user2.sign_in_count += 1;\n",[35,169,170],{"id":170},"字段初始化简写与结构体更新语法",[24,172,173],{},"如果变量名和字段名相同，可以省略冒号和值：",[42,175,177],{"className":44,"code":176,"language":12,"meta":46,"style":46},"fn build_user(username: String) -> User {\n    User {\n        active: true,\n        username,              \u002F\u002F 简写\n        sign_in_count: 1,\n    }\n}\n",[48,178,179,184,189,194,199,204,209],{"__ignoreMap":46},[51,180,181],{"class":53,"line":54},[51,182,183],{},"fn build_user(username: String) -> User {\n",[51,185,186],{"class":53,"line":60},[51,187,188],{},"    User {\n",[51,190,191],{"class":53,"line":66},[51,192,193],{},"        active: true,\n",[51,195,196],{"class":53,"line":72},[51,197,198],{},"        username,              \u002F\u002F 简写\n",[51,200,201],{"class":53,"line":78},[51,202,203],{},"        sign_in_count: 1,\n",[51,205,206],{"class":53,"line":164},[51,207,208],{},"    }\n",[51,210,212],{"class":53,"line":211},7,[51,213,81],{},[24,215,216,217,220],{},"想基于已有实例创建新实例，只修改部分字段时，使用 ",[48,218,219],{},".."," 更新语法：",[42,222,224],{"className":44,"code":223,"language":12,"meta":46,"style":46},"let user3 = User {\n    username: String::from(\"charlie\"),\n    ..user2            \u002F\u002F 其余字段使用 user2 的值\n};\n",[48,225,226,231,236,241],{"__ignoreMap":46},[51,227,228],{"class":53,"line":54},[51,229,230],{},"let user3 = User {\n",[51,232,233],{"class":53,"line":60},[51,234,235],{},"    username: String::from(\"charlie\"),\n",[51,237,238],{"class":53,"line":66},[51,239,240],{},"    ..user2            \u002F\u002F 其余字段使用 user2 的值\n",[51,242,243],{"class":53,"line":72},[51,244,114],{},[24,246,247,248,251,252,255,256,259,260,263,264,266],{},"注意：",[48,249,250],{},"..user2"," 会移动 ",[48,253,254],{},"user2"," 中未实现 ",[48,257,258],{},"Copy"," 的字段（比如 ",[48,261,262],{},"String","），此后 ",[48,265,254],{}," 不能再整体使用，但未移动的字段依然有效。",[35,268,269],{"id":269},"元组结构体与单元结构体",[24,271,272,276],{},[273,274,275],"strong",{},"元组结构体"," 没有字段名，只有类型：",[42,278,280],{"className":44,"code":279,"language":12,"meta":46,"style":46},"struct Color(i32, i32, i32);\nlet black = Color(0, 0, 0);\nprintln!(\"{}\", black.0); \u002F\u002F 通过索引访问\n",[48,281,282,287,292],{"__ignoreMap":46},[51,283,284],{"class":53,"line":54},[51,285,286],{},"struct Color(i32, i32, i32);\n",[51,288,289],{"class":53,"line":60},[51,290,291],{},"let black = Color(0, 0, 0);\n",[51,293,294],{"class":53,"line":66},[51,295,296],{},"println!(\"{}\", black.0); \u002F\u002F 通过索引访问\n",[24,298,299,302],{},[273,300,301],{},"单元结构体"," 不保存任何数据，仅作为标记类型，常用于实现 trait：",[42,304,306],{"className":44,"code":305,"language":12,"meta":46,"style":46},"struct AlwaysEqual;\nlet subject = AlwaysEqual;\n",[48,307,308,313],{"__ignoreMap":46},[51,309,310],{"class":53,"line":54},[51,311,312],{},"struct AlwaysEqual;\n",[51,314,315],{"class":53,"line":60},[51,316,317],{},"let subject = AlwaysEqual;\n",[35,319,320],{"id":320},"方法与关联函数",[24,322,323,326,327,330],{},[48,324,325],{},"impl"," 块为结构体定义方法。方法的第一个参数是 ",[48,328,329],{},"self"," 的某种形式：",[332,333,334,341,347],"ul",{},[335,336,337,340],"li",{},[48,338,339],{},"&self","：不可变借用，读取数据。",[335,342,343,346],{},[48,344,345],{},"&mut self","：可变借用，修改数据。",[335,348,349,351],{},[48,350,329],{},"：获取所有权，消耗结构体。",[42,353,355],{"className":44,"code":354,"language":12,"meta":46,"style":46},"impl User {\n    fn deactivate(&mut self) {\n        self.active = false;\n    }\n}\n",[48,356,357,362,367,372,376],{"__ignoreMap":46},[51,358,359],{"class":53,"line":54},[51,360,361],{},"impl User {\n",[51,363,364],{"class":53,"line":60},[51,365,366],{},"    fn deactivate(&mut self) {\n",[51,368,369],{"class":53,"line":66},[51,370,371],{},"        self.active = false;\n",[51,373,374],{"class":53,"line":72},[51,375,208],{},[51,377,378],{"class":53,"line":78},[51,379,81],{},[24,381,382,385,386,388,389,392],{},[273,383,384],{},"关联函数"," 不以 ",[48,387,329],{}," 为参数，通常用作构造函数，调用时用 ",[48,390,391],{},"::","：",[42,394,396],{"className":44,"code":395,"language":12,"meta":46,"style":46},"impl User {\n    fn new(username: String) -> Self {\n        User {\n            active: true,\n            username,\n            sign_in_count: 1,\n        }\n    }\n}\nlet u = User::new(String::from(\"dave\"));\n",[48,397,398,402,407,412,417,422,427,432,437,442],{"__ignoreMap":46},[51,399,400],{"class":53,"line":54},[51,401,361],{},[51,403,404],{"class":53,"line":60},[51,405,406],{},"    fn new(username: String) -> Self {\n",[51,408,409],{"class":53,"line":66},[51,410,411],{},"        User {\n",[51,413,414],{"class":53,"line":72},[51,415,416],{},"            active: true,\n",[51,418,419],{"class":53,"line":78},[51,420,421],{},"            username,\n",[51,423,424],{"class":53,"line":164},[51,425,426],{},"            sign_in_count: 1,\n",[51,428,429],{"class":53,"line":211},[51,430,431],{},"        }\n",[51,433,435],{"class":53,"line":434},8,[51,436,208],{},[51,438,440],{"class":53,"line":439},9,[51,441,81],{},[51,443,445],{"class":53,"line":444},10,[51,446,447],{},"let u = User::new(String::from(\"dave\"));\n",[35,449,450],{"id":450},"调试输出",[24,452,453,454,457,458,461],{},"通过为结构体添加 ",[48,455,456],{},"#[derive(Debug)]"," 属性，可以自动实现 ",[48,459,460],{},"Debug"," trait，方便打印调试信息：",[42,463,465],{"className":44,"code":464,"language":12,"meta":46,"style":46},"#[derive(Debug)]\nstruct User { \u002F* ... *\u002F }\nprintln!(\"{:?}\", user1);\n",[48,466,467,472,477],{"__ignoreMap":46},[51,468,469],{"class":53,"line":54},[51,470,471],{},"#[derive(Debug)]\n",[51,473,474],{"class":53,"line":60},[51,475,476],{},"struct User { \u002F* ... *\u002F }\n",[51,478,479],{"class":53,"line":66},[51,480,481],{},"println!(\"{:?}\", user1);\n",[27,483,485],{"id":484},"_42-枚举enum与模式匹配","4.2 枚举（enum）与模式匹配",[24,487,488],{},"枚举让你定义一个类型，其值可以是几个固定变体之一，且每个变体可以携带不同类型和大小的数据，比很多语言中的联合体强大得多。",[35,490,491],{"id":491},"枚举定义",[24,493,494],{},"一个典型的消息枚举：",[42,496,498],{"className":44,"code":497,"language":12,"meta":46,"style":46},"enum Message {\n    Quit,\n    Move { x: i32, y: i32 },\n    Write(String),\n    ChangeColor(i32, i32, i32),\n}\n",[48,499,500,505,510,515,520,525],{"__ignoreMap":46},[51,501,502],{"class":53,"line":54},[51,503,504],{},"enum Message {\n",[51,506,507],{"class":53,"line":60},[51,508,509],{},"    Quit,\n",[51,511,512],{"class":53,"line":66},[51,513,514],{},"    Move { x: i32, y: i32 },\n",[51,516,517],{"class":53,"line":72},[51,518,519],{},"    Write(String),\n",[51,521,522],{"class":53,"line":78},[51,523,524],{},"    ChangeColor(i32, i32, i32),\n",[51,526,527],{"class":53,"line":164},[51,528,81],{},[24,530,531],{},"每个变体可以：",[332,533,534,541,547],{},[335,535,536,537,540],{},"无数据（",[48,538,539],{},"Quit","）",[335,542,543,544,540],{},"带匿名字段（",[48,545,546],{},"Write(String)",[335,548,549,550,540],{},"带命名字段（",[48,551,552],{},"Move { x, y }",[24,554,555],{},"枚举的强大之处在于：一个值可以是这些变体中的任何一个，但处理它时必须通过模式匹配穷尽所有可能。",[35,557,559,562],{"id":558},"optiont用类型系统取代空指针",[48,560,561],{},"Option\u003CT>","：用类型系统取代空指针",[24,564,565,568],{},[48,566,567],{},"Option"," 是标准库预定义的枚举，表达了“要么有值，要么什么都没有”：",[42,570,572],{"className":44,"code":571,"language":12,"meta":46,"style":46},"enum Option\u003CT> {\n    None,\n    Some(T),\n}\n",[48,573,574,579,584,589],{"__ignoreMap":46},[51,575,576],{"class":53,"line":54},[51,577,578],{},"enum Option\u003CT> {\n",[51,580,581],{"class":53,"line":60},[51,582,583],{},"    None,\n",[51,585,586],{"class":53,"line":66},[51,587,588],{},"    Some(T),\n",[51,590,591],{"class":53,"line":72},[51,592,81],{},[24,594,595,596,599,600,603,604,607,608,610,611,614],{},"你不需要手动 ",[48,597,598],{},"use","，",[48,601,602],{},"Option::Some"," 和 ",[48,605,606],{},"Option::None"," 直接可用。对一个 ",[48,609,567],{},"，必须显式处理 ",[48,612,613],{},"None"," 情况，从编译期避免空指针问题：",[42,616,618],{"className":44,"code":617,"language":12,"meta":46,"style":46},"let x: Option\u003Ci32> = Some(5);\nlet y: Option\u003Ci32> = None;\n",[48,619,620,625],{"__ignoreMap":46},[51,621,622],{"class":53,"line":54},[51,623,624],{},"let x: Option\u003Ci32> = Some(5);\n",[51,626,627],{"class":53,"line":60},[51,628,629],{},"let y: Option\u003Ci32> = None;\n",[35,631,633,636],{"id":632},"resultt-e错误处理的核心",[48,634,635],{},"Result\u003CT, E>","：错误处理的核心",[24,638,639,642],{},[48,640,641],{},"Result"," 表示可能失败的操作：",[42,644,646],{"className":44,"code":645,"language":12,"meta":46,"style":46},"enum Result\u003CT, E> {\n    Ok(T),\n    Err(E),\n}\n",[48,647,648,653,658,663],{"__ignoreMap":46},[51,649,650],{"class":53,"line":54},[51,651,652],{},"enum Result\u003CT, E> {\n",[51,654,655],{"class":53,"line":60},[51,656,657],{},"    Ok(T),\n",[51,659,660],{"class":53,"line":66},[51,661,662],{},"    Err(E),\n",[51,664,665],{"class":53,"line":72},[51,666,81],{},[24,668,669,670,672],{},"处理 ",[48,671,641],{}," 时也要面对成功和失败两条路径：",[42,674,676],{"className":44,"code":675,"language":12,"meta":46,"style":46},"let f = std::fs::File::open(\"file.txt\");\nmatch f {\n    Ok(file) => { \u002F* 使用文件 *\u002F }\n    Err(error) => { \u002F* 处理错误 *\u002F }\n}\n",[48,677,678,683,688,693,698],{"__ignoreMap":46},[51,679,680],{"class":53,"line":54},[51,681,682],{},"let f = std::fs::File::open(\"file.txt\");\n",[51,684,685],{"class":53,"line":60},[51,686,687],{},"match f {\n",[51,689,690],{"class":53,"line":66},[51,691,692],{},"    Ok(file) => { \u002F* 使用文件 *\u002F }\n",[51,694,695],{"class":53,"line":72},[51,696,697],{},"    Err(error) => { \u002F* 处理错误 *\u002F }\n",[51,699,700],{"class":53,"line":78},[51,701,81],{},[24,703,704,705,707],{},"后续章节会深入 ",[48,706,641],{}," 的组合子和传播方式。",[35,709,711,714],{"id":710},"match-表达式",[48,712,713],{},"match"," 表达式",[24,716,717,719],{},[48,718,713],{}," 与枚举天然契合。它会强制检查所有变体（穷尽性检查），每个分支叫一个“臂”（arm）。模式可以包含解构、或运算符、范围、守卫等。",[42,721,723],{"className":44,"code":722,"language":12,"meta":46,"style":46},"match msg {\n    Message::Quit => println!(\"退出\"),\n    Message::Move { x, y } => println!(\"移动到 ({}, {})\", x, y),\n    Message::Write(text) => println!(\"写入: {}\", text),\n    Message::ChangeColor(r, g, b) => println!(\"改变颜色: ({}, {}, {})\", r, g, b),\n}\n",[48,724,725,730,735,740,745,750],{"__ignoreMap":46},[51,726,727],{"class":53,"line":54},[51,728,729],{},"match msg {\n",[51,731,732],{"class":53,"line":60},[51,733,734],{},"    Message::Quit => println!(\"退出\"),\n",[51,736,737],{"class":53,"line":66},[51,738,739],{},"    Message::Move { x, y } => println!(\"移动到 ({}, {})\", x, y),\n",[51,741,742],{"class":53,"line":72},[51,743,744],{},"    Message::Write(text) => println!(\"写入: {}\", text),\n",[51,746,747],{"class":53,"line":78},[51,748,749],{},"    Message::ChangeColor(r, g, b) => println!(\"改变颜色: ({}, {}, {})\", r, g, b),\n",[51,751,752],{"class":53,"line":164},[51,753,81],{},[755,756,757],"h4",{"id":757},"多模式与范围",[24,759,760,761,764],{},"用 ",[48,762,763],{},"|"," 在一个臂中匹配多个模式：",[42,766,768],{"className":44,"code":767,"language":12,"meta":46,"style":46},"match x {\n    1 | 2 => println!(\"一或二\"),\n    _ => println!(\"其他\"),\n}\n",[48,769,770,775,780,785],{"__ignoreMap":46},[51,771,772],{"class":53,"line":54},[51,773,774],{},"match x {\n",[51,776,777],{"class":53,"line":60},[51,778,779],{},"    1 | 2 => println!(\"一或二\"),\n",[51,781,782],{"class":53,"line":66},[51,783,784],{},"    _ => println!(\"其他\"),\n",[51,786,787],{"class":53,"line":72},[51,788,81],{},[24,790,791],{},"匹配范围（要求值类型支持）：",[42,793,795],{"className":44,"code":794,"language":12,"meta":46,"style":46},"match x {\n    1..=5 => println!(\"1到5\"),\n    _ => println!(\"其他\"),\n}\n",[48,796,797,801,806,810],{"__ignoreMap":46},[51,798,799],{"class":53,"line":54},[51,800,774],{},[51,802,803],{"class":53,"line":60},[51,804,805],{},"    1..=5 => println!(\"1到5\"),\n",[51,807,808],{"class":53,"line":66},[51,809,784],{},[51,811,812],{"class":53,"line":72},[51,813,81],{},[755,815,816],{"id":816},"匹配守卫",[24,818,819,820,823],{},"在模式后加上 ",[48,821,822],{},"if"," 条件来进一步过滤：",[42,825,827],{"className":44,"code":826,"language":12,"meta":46,"style":46},"match some_number {\n    n if n % 2 == 0 => println!(\"偶数\"),\n    _ => println!(\"奇数\"),\n}\n",[48,828,829,834,839,844],{"__ignoreMap":46},[51,830,831],{"class":53,"line":54},[51,832,833],{},"match some_number {\n",[51,835,836],{"class":53,"line":60},[51,837,838],{},"    n if n % 2 == 0 => println!(\"偶数\"),\n",[51,840,841],{"class":53,"line":66},[51,842,843],{},"    _ => println!(\"奇数\"),\n",[51,845,846],{"class":53,"line":72},[51,847,81],{},[35,849,851,603,854],{"id":850},"if-let-和-while-let",[48,852,853],{},"if let",[48,855,856],{},"while let",[24,858,859,860,392],{},"如果只关心一种模式，可以使用更简洁的 ",[48,861,853],{},[42,863,865],{"className":44,"code":864,"language":12,"meta":46,"style":46},"if let Message::Write(text) = msg {\n    println!(\"写入 {text}\");\n} else {\n    println!(\"不是写入消息\");\n}\n",[48,866,867,872,877,882,887],{"__ignoreMap":46},[51,868,869],{"class":53,"line":54},[51,870,871],{},"if let Message::Write(text) = msg {\n",[51,873,874],{"class":53,"line":60},[51,875,876],{},"    println!(\"写入 {text}\");\n",[51,878,879],{"class":53,"line":66},[51,880,881],{},"} else {\n",[51,883,884],{"class":53,"line":72},[51,885,886],{},"    println!(\"不是写入消息\");\n",[51,888,889],{"class":53,"line":78},[51,890,81],{},[24,892,893,895],{},[48,894,856],{}," 则持续匹配，常用于迭代器或通道：",[42,897,899],{"className":44,"code":898,"language":12,"meta":46,"style":46},"while let Some(top) = stack.pop() {\n    println!(\"{top}\");\n}\n",[48,900,901,906,911],{"__ignoreMap":46},[51,902,903],{"class":53,"line":54},[51,904,905],{},"while let Some(top) = stack.pop() {\n",[51,907,908],{"class":53,"line":60},[51,909,910],{},"    println!(\"{top}\");\n",[51,912,913],{"class":53,"line":66},[51,914,81],{},[35,916,917],{"id":917},"解构",[24,919,920],{},"模式匹配的强大离不开解构。你可以随手拆开复合数据。",[24,922,923],{},"元组解构：",[42,925,927],{"className":44,"code":926,"language":12,"meta":46,"style":46},"let pair = (1, \"hello\");\nlet (x, y) = pair;\nprintln!(\"{} {}\", x, y);\n",[48,928,929,934,939],{"__ignoreMap":46},[51,930,931],{"class":53,"line":54},[51,932,933],{},"let pair = (1, \"hello\");\n",[51,935,936],{"class":53,"line":60},[51,937,938],{},"let (x, y) = pair;\n",[51,940,941],{"class":53,"line":66},[51,942,943],{},"println!(\"{} {}\", x, y);\n",[24,945,946],{},"结构体解构：",[42,948,950],{"className":44,"code":949,"language":12,"meta":46,"style":46},"struct Point { x: i32, y: i32 }\nlet p = Point { x: 10, y: 20 };\nlet Point { x, y } = p;\n",[48,951,952,957,962],{"__ignoreMap":46},[51,953,954],{"class":53,"line":54},[51,955,956],{},"struct Point { x: i32, y: i32 }\n",[51,958,959],{"class":53,"line":60},[51,960,961],{},"let p = Point { x: 10, y: 20 };\n",[51,963,964],{"class":53,"line":66},[51,965,966],{},"let Point { x, y } = p;\n",[24,968,969],{},"也可以部分解构或重命名：",[42,971,973],{"className":44,"code":972,"language":12,"meta":46,"style":46},"let Point { x: a, y: b } = p;  \u002F\u002F a == 10, b == 20\n",[48,974,975],{"__ignoreMap":46},[51,976,977],{"class":53,"line":54},[51,978,972],{},[27,980,982],{"id":981},"_43-集合类型","4.3 集合类型",[24,984,985],{},"Rust 标准库提供了多种通用集合类型，它们分配在堆上，可以动态增长。",[35,987,989,992],{"id":988},"vect动态数组",[48,990,991],{},"Vec\u003CT>","：动态数组",[24,994,995,998],{},[48,996,997],{},"Vec"," 是最常用的集合，可以存储一系列相同类型的值，按需自动扩容。",[42,1000,1002],{"className":44,"code":1001,"language":12,"meta":46,"style":46},"let mut v: Vec\u003Ci32> = Vec::new();\nv.push(1);\nv.push(2);\n",[48,1003,1004,1009,1014],{"__ignoreMap":46},[51,1005,1006],{"class":53,"line":54},[51,1007,1008],{},"let mut v: Vec\u003Ci32> = Vec::new();\n",[51,1010,1011],{"class":53,"line":60},[51,1012,1013],{},"v.push(1);\n",[51,1015,1016],{"class":53,"line":66},[51,1017,1018],{},"v.push(2);\n",[24,1020,1021,1022,1025],{},"使用 ",[48,1023,1024],{},"vec!"," 宏创建并初始化：",[42,1027,1029],{"className":44,"code":1028,"language":12,"meta":46,"style":46},"let v = vec![1, 2, 3, 4, 5];\n",[48,1030,1031],{"__ignoreMap":46},[51,1032,1033],{"class":53,"line":54},[51,1034,1028],{},[24,1036,1037],{},"访问元素有两种方式：",[332,1039,1040,1047],{},[335,1041,1042,1043,1046],{},"索引 ",[48,1044,1045],{},"&v[2]","：越界时会 panic。",[335,1048,1049,1052,1053,1056],{},[48,1050,1051],{},"v.get(2)"," 返回 ",[48,1054,1055],{},"Option\u003C&T>","，安全处理。",[42,1058,1060],{"className":44,"code":1059,"language":12,"meta":46,"style":46},"match v.get(10) {\n    Some(value) => println!(\"{value}\"),\n    None => println!(\"没有这个元素\"),\n}\n",[48,1061,1062,1067,1072,1077],{"__ignoreMap":46},[51,1063,1064],{"class":53,"line":54},[51,1065,1066],{},"match v.get(10) {\n",[51,1068,1069],{"class":53,"line":60},[51,1070,1071],{},"    Some(value) => println!(\"{value}\"),\n",[51,1073,1074],{"class":53,"line":66},[51,1075,1076],{},"    None => println!(\"没有这个元素\"),\n",[51,1078,1079],{"class":53,"line":72},[51,1080,81],{},[24,1082,1083],{},"遍历：",[42,1085,1087],{"className":44,"code":1086,"language":12,"meta":46,"style":46},"for i in &v {\n    println!(\"{i}\");\n}\nfor i in &mut v {\n    *i += 1;   \u002F\u002F 通过解引用指针修改值\n}\n",[48,1088,1089,1094,1099,1103,1108,1116],{"__ignoreMap":46},[51,1090,1091],{"class":53,"line":54},[51,1092,1093],{},"for i in &v {\n",[51,1095,1096],{"class":53,"line":60},[51,1097,1098],{},"    println!(\"{i}\");\n",[51,1100,1101],{"class":53,"line":66},[51,1102,81],{},[51,1104,1105],{"class":53,"line":72},[51,1106,1107],{},"for i in &mut v {\n",[51,1109,1110,1113],{"class":53,"line":78},[51,1111,1112],{},"    *i += 1;",[51,1114,1115],{},"   \u002F\u002F 通过解引用指针修改值\n",[51,1117,1118],{"class":53,"line":164},[51,1119,81],{},[24,1121,1122,1124],{},[48,1123,997],{}," 可以通过切片视图访问其全部或部分内容：",[42,1126,1128],{"className":44,"code":1127,"language":12,"meta":46,"style":46},"let slice: &[i32] = &v[1..3];\n",[48,1129,1130],{"__ignoreMap":46},[51,1131,1132],{"class":53,"line":54},[51,1133,1127],{},[35,1135,1137,1139,1140],{"id":1136},"string-与-str",[48,1138,262],{}," 与 ",[48,1141,1142],{},"&str",[24,1144,1145,1146,1148],{},"Rust 的字符串相当严谨。",[48,1147,262],{}," 是一个可增长的、拥有所有权的 UTF-8 编码字符串，分配在堆上。",[42,1150,1152],{"className":44,"code":1151,"language":12,"meta":46,"style":46},"let mut s = String::from(\"hello\");\ns.push_str(\", world\");\ns.push('!');\n",[48,1153,1154,1159,1164],{"__ignoreMap":46},[51,1155,1156],{"class":53,"line":54},[51,1157,1158],{},"let mut s = String::from(\"hello\");\n",[51,1160,1161],{"class":53,"line":60},[51,1162,1163],{},"s.push_str(\", world\");\n",[51,1165,1166],{"class":53,"line":66},[51,1167,1168],{},"s.push('!');\n",[24,1170,760,1171,1174,1175,1177,1178,1180],{},[48,1172,1173],{},"+"," 拼接时，左侧必须是 ",[48,1176,262],{},"，右侧是 ",[48,1179,1142],{},"，且会获取左侧的所有权：",[42,1182,1184],{"className":44,"code":1183,"language":12,"meta":46,"style":46},"let s1 = String::from(\"hello\");\nlet s2 = String::from(\" world\");\nlet s3 = s1 + &s2;   \u002F\u002F s1 所有权被移走，此后不可再用 s1\n\u002F\u002F println!(\"{s1}\"); \u002F\u002F 编译错误\n",[48,1185,1186,1191,1196,1201],{"__ignoreMap":46},[51,1187,1188],{"class":53,"line":54},[51,1189,1190],{},"let s1 = String::from(\"hello\");\n",[51,1192,1193],{"class":53,"line":60},[51,1194,1195],{},"let s2 = String::from(\" world\");\n",[51,1197,1198],{"class":53,"line":66},[51,1199,1200],{},"let s3 = s1 + &s2;   \u002F\u002F s1 所有权被移走，此后不可再用 s1\n",[51,1202,1203,1206],{"class":53,"line":72},[51,1204,1205],{},"\u002F\u002F println!(\"{s1}\");",[51,1207,1208],{}," \u002F\u002F 编译错误\n",[24,1210,1211,1214],{},[48,1212,1213],{},"format!"," 按引用格式化，不拿走所有权，更灵活：",[42,1216,1218],{"className":44,"code":1217,"language":12,"meta":46,"style":46},"let hello = String::from(\"hello\");\nlet world = String::from(\"world\");\nlet s = format!(\"{}-{}\", hello, world); \u002F\u002F hello、world 仍可使用\n",[48,1219,1220,1225,1230],{"__ignoreMap":46},[51,1221,1222],{"class":53,"line":54},[51,1223,1224],{},"let hello = String::from(\"hello\");\n",[51,1226,1227],{"class":53,"line":60},[51,1228,1229],{},"let world = String::from(\"world\");\n",[51,1231,1232],{"class":53,"line":66},[51,1233,1234],{},"let s = format!(\"{}-{}\", hello, world); \u002F\u002F hello、world 仍可使用\n",[24,1236,1237,1239,1240,392],{},[48,1238,1142],{}," 是字符串切片，本质是对内存某段有效 UTF-8 数据的引用。字符串字面量就是 ",[48,1241,1142],{},[42,1243,1245],{"className":44,"code":1244,"language":12,"meta":46,"style":46},"let literal: &str = \"I'm static\";\n",[48,1246,1247],{"__ignoreMap":46},[51,1248,1249],{"class":53,"line":54},[51,1250,1244],{},[24,1252,1253,1254,1256,1257,1260,1261,1263],{},"许多 API 使用 ",[48,1255,1142],{}," 作为参数，因为 ",[48,1258,1259],{},"&String"," 会自动强制转换为 ",[48,1262,1142],{},"，让接口更加通用。",[35,1265,1267],{"id":1266},"hashmapk-v",[48,1268,1269],{},"HashMap\u003CK, V>",[24,1271,1272,1273,603,1276,1279],{},"哈希映射存储键值对，键类型必须实现 ",[48,1274,1275],{},"Eq",[48,1277,1278],{},"Hash"," trait。",[42,1281,1283],{"className":44,"code":1282,"language":12,"meta":46,"style":46},"use std::collections::HashMap;\n\nlet mut scores = HashMap::new();\nscores.insert(String::from(\"Blue\"), 10);\nscores.insert(String::from(\"Yellow\"), 50);\n",[48,1284,1285,1290,1296,1301,1306],{"__ignoreMap":46},[51,1286,1287],{"class":53,"line":54},[51,1288,1289],{},"use std::collections::HashMap;\n",[51,1291,1292],{"class":53,"line":60},[51,1293,1295],{"emptyLinePlaceholder":1294},true,"\n",[51,1297,1298],{"class":53,"line":66},[51,1299,1300],{},"let mut scores = HashMap::new();\n",[51,1302,1303],{"class":53,"line":72},[51,1304,1305],{},"scores.insert(String::from(\"Blue\"), 10);\n",[51,1307,1308],{"class":53,"line":78},[51,1309,1310],{},"scores.insert(String::from(\"Yellow\"), 50);\n",[24,1312,1313,1314,1317,1318,392],{},"通过 ",[48,1315,1316],{},"get"," 按键取值，返回 ",[48,1319,1320],{},"Option\u003C&V>",[42,1322,1324],{"className":44,"code":1323,"language":12,"meta":46,"style":46},"let team = String::from(\"Blue\");\nlet score = scores.get(&team).copied().unwrap_or(0);\n",[48,1325,1326,1331],{"__ignoreMap":46},[51,1327,1328],{"class":53,"line":54},[51,1329,1330],{},"let team = String::from(\"Blue\");\n",[51,1332,1333],{"class":53,"line":60},[51,1334,1335],{},"let score = scores.get(&team).copied().unwrap_or(0);\n",[24,1337,1338],{},"更新值的方法：",[332,1340,1341,1347],{},[335,1342,1343,1346],{},[48,1344,1345],{},"insert"," 会覆盖旧值。",[335,1348,1349,1352],{},[48,1350,1351],{},"entry"," API 根据键是否存在，决定插入还是修改：",[42,1354,1356],{"className":44,"code":1355,"language":12,"meta":46,"style":46},"scores.entry(String::from(\"Blue\")).or_insert(50); \u002F\u002F 存在则不动\nscores.entry(String::from(\"Red\")).or_insert(30);  \u002F\u002F 不存在则插入\n",[48,1357,1358,1363],{"__ignoreMap":46},[51,1359,1360],{"class":53,"line":54},[51,1361,1362],{},"scores.entry(String::from(\"Blue\")).or_insert(50); \u002F\u002F 存在则不动\n",[51,1364,1365],{"class":53,"line":60},[51,1366,1367],{},"scores.entry(String::from(\"Red\")).or_insert(30);  \u002F\u002F 不存在则插入\n",[24,1369,760,1370,1372],{},[48,1371,1351],{}," 返回的可变引用还可以对旧值进行更新：",[42,1374,1376],{"className":44,"code":1375,"language":12,"meta":46,"style":46},"let count = scores.entry(String::from(\"Blue\")).or_insert(0);\n*count += 10;\n",[48,1377,1378,1383],{"__ignoreMap":46},[51,1379,1380],{"class":53,"line":54},[51,1381,1382],{},"let count = scores.entry(String::from(\"Blue\")).or_insert(0);\n",[51,1384,1385],{"class":53,"line":60},[51,1386,1387],{},"*count += 10;\n",[24,1389,1083],{},[42,1391,1393],{"className":44,"code":1392,"language":12,"meta":46,"style":46},"for (key, value) in &scores {\n    println!(\"{key}: {value}\");\n}\n",[48,1394,1395,1400,1405],{"__ignoreMap":46},[51,1396,1397],{"class":53,"line":54},[51,1398,1399],{},"for (key, value) in &scores {\n",[51,1401,1402],{"class":53,"line":60},[51,1403,1404],{},"    println!(\"{key}: {value}\");\n",[51,1406,1407],{"class":53,"line":66},[51,1408,81],{},[35,1410,1411],{"id":1411},"其他集合类型",[24,1413,1414],{},"Rust 提供的最常用集合还包括：",[332,1416,1417,1429,1437,1449],{},[335,1418,1419,1424,1425,1428],{},[273,1420,1421],{},[48,1422,1423],{},"HashSet\u003CT>","：基于 ",[48,1426,1427],{},"HashMap"," 的集合，保证元素唯一，提供高效的插入、查询和删除。",[335,1430,1431,1436],{},[273,1432,1433],{},[48,1434,1435],{},"VecDeque\u003CT>","：双端队列，可在头尾高效地插入和移除，内部是环形缓冲。",[335,1438,1439,1444,1445,1448],{},[273,1440,1441],{},[48,1442,1443],{},"LinkedList\u003CT>","：双向链表，适合在任意位置频繁插入、分割列表的场景。但在连续内存遍历方面性能不如 ",[48,1446,1447],{},"VecDeque","。",[335,1450,1451,1456,1457,1460],{},[273,1452,1453],{},[48,1454,1455],{},"BinaryHeap\u003CT>","：基于二叉堆的最大优先队列，",[48,1458,1459],{},"peek"," 返回最大元素。",[24,1462,1463],{},"选择集合时要考虑访问模式、性能特性和内存布局。",[35,1465,1467],{"id":1466},"迭代器iterator初步","迭代器（Iterator）初步",[24,1469,1470],{},"迭代器是处理集合的统一抽象，Rust 的迭代器零开销且功能极其强大。",[24,1472,1473],{},"三种产生迭代器的常用方法：",[332,1475,1476,1482,1488],{},[335,1477,1478,1481],{},[48,1479,1480],{},".iter()","：返回不可变引用的迭代器，不消耗集合。",[335,1483,1484,1487],{},[48,1485,1486],{},".iter_mut()","：返回可变引用的迭代器。",[335,1489,1490,1493],{},[48,1491,1492],{},".into_iter()","：获取所有权，消耗集合并产生元素。",[42,1495,1497],{"className":44,"code":1496,"language":12,"meta":46,"style":46},"let v = vec![1, 2, 3];\nfor val in v.iter() {\n    println!(\"{val}\");\n}\n\u002F\u002F v 仍然可用\n",[48,1498,1499,1504,1509,1514,1518],{"__ignoreMap":46},[51,1500,1501],{"class":53,"line":54},[51,1502,1503],{},"let v = vec![1, 2, 3];\n",[51,1505,1506],{"class":53,"line":60},[51,1507,1508],{},"for val in v.iter() {\n",[51,1510,1511],{"class":53,"line":66},[51,1512,1513],{},"    println!(\"{val}\");\n",[51,1515,1516],{"class":53,"line":72},[51,1517,81],{},[51,1519,1520],{"class":53,"line":78},[51,1521,1522],{},"\u002F\u002F v 仍然可用\n",[24,1524,1525,1526,1529,1530,1529,1533,1536,1537,1540,1541,1544,1545,1548],{},"迭代器可以链式调用各种适配器（",[48,1527,1528],{},"map","、",[48,1531,1532],{},"filter",[48,1534,1535],{},"collect"," 等），后续章节将详细介绍。这里只需知道：",[48,1538,1539],{},"for"," 循环本质上是 ",[48,1542,1543],{},"into_iter()"," 的语法糖，而标准库中的集合都实现了 ",[48,1546,1547],{},"IntoIterator","，让它们能自然地在循环中工作。",[24,1550,1551,1552,1448],{},"结构体让你把数据组织成有意义的整体，枚举使类型能承载多种可能状态，而集合则负责高效存储和遍历成批数据。下一章请阅读 ",[1553,1554,1556],"a",{"href":1555},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ft","泛型与 Trait",[27,1558,1559],{"id":1559},"参考文献",[1561,1562,1563,1576],"table",{},[1564,1565,1566],"thead",{},[1567,1568,1569,1573],"tr",{},[1570,1571,1572],"th",{},"资料",[1570,1574,1575],{},"说明",[1577,1578,1579,1593,1607],"tbody",{},[1567,1580,1581,1590],{},[1582,1583,1584],"td",{},[1553,1585,1589],{"href":1586,"rel":1587},"https:\u002F\u002Fdoc.rust-lang.org\u002Fbook\u002Fch05-00-structs.html",[1588],"nofollow","Structs",[1582,1591,1592],{},"官方书第 5 章",[1567,1594,1595,1602],{},[1582,1596,1597],{},[1553,1598,1601],{"href":1599,"rel":1600},"https:\u002F\u002Fdoc.rust-lang.org\u002Fbook\u002Fch06-00-enums.html",[1588],"Enums",[1582,1603,1604,1605],{},"枚举与 ",[48,1606,713],{},[1567,1608,1609,1616],{},[1582,1610,1611],{},[1553,1612,1615],{"href":1613,"rel":1614},"https:\u002F\u002Fdoc.rust-lang.org\u002Fbook\u002Fch08-00-common-collections.html",[1588],"Collections",[1582,1617,1618,1529,1620,1529,1622],{},[48,1619,997],{},[48,1621,262],{},[48,1623,1427],{},[1625,1626,1627],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":46,"searchDepth":60,"depth":60,"links":1629},[1630,1637,1649,1658],{"id":29,"depth":60,"text":30,"children":1631},[1632,1633,1634,1635,1636],{"id":37,"depth":66,"text":37},{"id":170,"depth":66,"text":170},{"id":269,"depth":66,"text":269},{"id":320,"depth":66,"text":320},{"id":450,"depth":66,"text":450},{"id":484,"depth":60,"text":485,"children":1638},[1639,1640,1642,1644,1646,1648],{"id":491,"depth":66,"text":491},{"id":558,"depth":66,"text":1641},"Option\u003CT>：用类型系统取代空指针",{"id":632,"depth":66,"text":1643},"Result\u003CT, E>：错误处理的核心",{"id":710,"depth":66,"text":1645},"match 表达式",{"id":850,"depth":66,"text":1647},"if let 和 while let",{"id":917,"depth":66,"text":917},{"id":981,"depth":60,"text":982,"children":1650},[1651,1653,1655,1656,1657],{"id":988,"depth":66,"text":1652},"Vec\u003CT>：动态数组",{"id":1136,"depth":66,"text":1654},"String 与 &str",{"id":1266,"depth":66,"text":1269},{"id":1411,"depth":66,"text":1411},{"id":1466,"depth":66,"text":1467},{"id":1559,"depth":60,"text":1559},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FRust\u002Fdata-type","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FRust\u002Fdata-type.md","md",{"items":1664},[1665,1669,1671,1675,1679,1683],{"path":1666,"title":1667,"description":1668,"category":10,"score":164},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fdocs","第八章：测试、文档与质量","Rust 将测试和文档视为语言的一等公民。通过内置的测试框架，你可以在项目里编写单元测试、集成测试以及随文档一起运行的示例测试，三者共用 cargo test 命令。配合 cargo doc 生成文档，形成了一套确保代码质量与可维护性…",{"path":1555,"title":1556,"description":1670,"category":10,"score":164},"泛型和 trait 是 Rust 实现代码复用与多态的两大支柱。前置：Rust 基础。泛型让代码可以工作在多种类型上而不牺牲性能，trait 定义了类型间的共享行为，二者结合形成了零成本抽象的强大表达能力。本章将深入泛型定义、trai…",{"path":1672,"title":1673,"description":1674,"category":10,"score":164},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ftype","第二章：基础语法与类型","Rust 的类型系统和语法设计处处体现着“安全”与“显式”的理念。这一章你将掌握变量绑定、基本类型、复合类型、函数定义以及所有基础控制流结构，它们是你写出任何 Rust 程序的基石。",{"path":1676,"title":1677,"description":1678,"category":10,"score":164},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fpackage","第七章：模块系统与包管理","Rust 的模块系统为代码组织、封装和复用提供了一套严谨但灵活的机制。包、crate、模块以及 use 路径相互配合，让你能够把项目拆解成清晰的功能单元，同时精确控制哪些对外可见。本章将带你系统掌握这些构建大型 Rust 项目所必需的…",{"path":1680,"title":1681,"description":1682,"category":10,"score":164},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fother","第十章：进阶特性与模式","Rust 的核心安全保证覆盖了绝大多数日常编程场景。但当你需要打破常规——无论是编写极致通用的抽象、与 C 库交互，还是内联优化——本章将带你进入 Rust 的深层能力：声明宏与过程宏、unsafe 的超能力与封装、高级类型系统技巧…",{"path":1684,"title":1685,"description":1686,"category":10,"score":164},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ferror","第五章：错误处理","Rust 将错误明确分为两类：不可恢复的错误与可恢复的错误。通过 panic! 处理前一种，Result 处理后一种，这让程序的错误路径不再是隐式的控制流，而是强类型、必须处理的代码分支。配合 Option 对缺失值的处理以及丰富的组…",{"series":1688,"title":12,"items":1689,"index":66,"prev":1715,"next":1716},"booklet\u002Fend\u002Frust",[1690,1694,1698,1702,1703,1705,1707,1709,1711,1713],{"path":1691,"title":1692,"date":1693,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fasync","第九章：并发与异步","2020-05-22",{"path":1695,"title":1696,"date":1697,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fbase","Rust 基础","2020-07-21",{"path":1699,"title":1700,"date":1701,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fcore","第三章：所有权、借用与生命周期（核心）","2023-05-09",{"path":7,"title":8,"date":14,"pinned":15},{"path":1666,"title":1667,"date":1704,"pinned":15},"2026-01-11",{"path":1684,"title":1685,"date":1706,"pinned":15},"2023-11-03",{"path":1680,"title":1681,"date":1708,"pinned":15},"2023-12-29",{"path":1676,"title":1677,"date":1710,"pinned":15},"2024-05-26",{"path":1555,"title":1556,"date":1712,"pinned":15},"2024-10-31",{"path":1672,"title":1673,"date":1714,"pinned":15},"2024-08-31",{"path":1699,"title":1700,"date":1701,"pinned":15},{"path":1666,"title":1667,"date":1704,"pinned":15}]