[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ft":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ft":1808,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ft":1834},{"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":1804,"stem":1805,"id":1806,"extension":1807},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ft","泛型与 Trait","泛型和 trait 是 Rust 实现代码复用与多态的两大支柱。前置：Rust 基础。泛型让代码可以工作在多种类型上而不牺牲性能，trait 定义了类型间的共享行为，二者结合形成了零成本抽象的强大表达能力。本章将深入泛型定义、trai…","技能小册",[12,13],"rust","t","2024-10-31",false,{"type":17,"value":18,"toc":1761},"minimark",[19,23,33,38,46,50,61,125,141,171,174,177,217,228,252,255,262,290,301,329,335,382,384,399,402,409,433,451,455,458,462,469,488,491,518,522,528,579,582,588,595,599,606,611,630,633,651,657,661,664,697,707,714,724,756,766,769,775,799,806,830,840,844,847,858,888,925,934,953,968,976,993,1040,1046,1060,1066,1076,1110,1119,1136,1169,1178,1187,1199,1232,1238,1248,1276,1281,1304,1345,1348,1352,1356,1370,1421,1434,1437,1440,1449,1452,1550,1557,1561,1564,1600,1612,1629,1636,1691,1694,1697,1700,1757],[20,21,8],"h1",{"id":22},"泛型与-trait",[24,25,26,27,32],"p",{},"泛型和 trait 是 Rust 实现代码复用与多态的两大支柱。前置：",[28,29,31],"a",{"href":30},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fbase","Rust 基础","。泛型让代码可以工作在多种类型上而不牺牲性能，trait 定义了类型间的共享行为，二者结合形成了零成本抽象的强大表达能力。本章将深入泛型定义、trait 的设计实现、标准库中最重要的 trait，以及一些高级模式。",[34,35,37],"h2",{"id":36},"_61-泛型","6.1 泛型",[24,39,40,41,45],{},"泛型允许你编写适用于多种类型的代码，同时编译器通过",[42,43,44],"strong",{},"单态化","为每个使用的具体类型生成特化版本，确保零运行时开销。",[47,48,49],"h3",{"id":49},"函数泛型",[24,51,52,53,57,58,60],{},"在函数签名中使用泛型参数 ",[54,55,56],"code",{},"T","，并为它附加 trait 约束以明确 ",[54,59,56],{}," 必须支持的操作。",[62,63,67],"pre",{"className":64,"code":65,"language":12,"meta":66,"style":66},"language-rust shiki shiki-themes material-theme-lighter github-light github-dark","fn largest\u003CT: PartialOrd>(list: &[T]) -> &T {\n    let mut largest = &list[0];\n    for item in list {\n        if item > largest {\n            largest = item;\n        }\n    }\n    largest\n}\n","",[54,68,69,77,83,89,95,101,107,113,119],{"__ignoreMap":66},[70,71,74],"span",{"class":72,"line":73},"line",1,[70,75,76],{},"fn largest\u003CT: PartialOrd>(list: &[T]) -> &T {\n",[70,78,80],{"class":72,"line":79},2,[70,81,82],{},"    let mut largest = &list[0];\n",[70,84,86],{"class":72,"line":85},3,[70,87,88],{},"    for item in list {\n",[70,90,92],{"class":72,"line":91},4,[70,93,94],{},"        if item > largest {\n",[70,96,98],{"class":72,"line":97},5,[70,99,100],{},"            largest = item;\n",[70,102,104],{"class":72,"line":103},6,[70,105,106],{},"        }\n",[70,108,110],{"class":72,"line":109},7,[70,111,112],{},"    }\n",[70,114,116],{"class":72,"line":115},8,[70,117,118],{},"    largest\n",[70,120,122],{"class":72,"line":121},9,[70,123,124],{},"}\n",[24,126,127,129,130,133,134,136,137,140],{},[54,128,56],{}," 后面的 ",[54,131,132],{},": PartialOrd"," 是 trait 约束，表示类型 ",[54,135,56],{}," 必须可比较大小。多个泛型参数用逗号分隔，也可用 ",[54,138,139],{},"where"," 子句提升可读性：",[62,142,144],{"className":64,"code":143,"language":12,"meta":66,"style":66},"fn some_fn\u003CT, U>(t: &T, u: &U) -> i32\nwhere\n    T: Display + Clone,\n    U: Clone + Debug,\n{ ... }\n",[54,145,146,151,156,161,166],{"__ignoreMap":66},[70,147,148],{"class":72,"line":73},[70,149,150],{},"fn some_fn\u003CT, U>(t: &T, u: &U) -> i32\n",[70,152,153],{"class":72,"line":79},[70,154,155],{},"where\n",[70,157,158],{"class":72,"line":85},[70,159,160],{},"    T: Display + Clone,\n",[70,162,163],{"class":72,"line":91},[70,164,165],{},"    U: Clone + Debug,\n",[70,167,168],{"class":72,"line":97},[70,169,170],{},"{ ... }\n",[47,172,173],{"id":173},"结构体与枚举泛型",[24,175,176],{},"结构体可以存储任意类型的数据：",[62,178,180],{"className":64,"code":179,"language":12,"meta":66,"style":66},"struct Point\u003CT> {\n    x: T,\n    y: T,\n}\n\nlet integer = Point { x: 5, y: 10 };\nlet float = Point { x: 1.0, y: 4.0 };\n",[54,181,182,187,192,197,201,207,212],{"__ignoreMap":66},[70,183,184],{"class":72,"line":73},[70,185,186],{},"struct Point\u003CT> {\n",[70,188,189],{"class":72,"line":79},[70,190,191],{},"    x: T,\n",[70,193,194],{"class":72,"line":85},[70,195,196],{},"    y: T,\n",[70,198,199],{"class":72,"line":91},[70,200,124],{},[70,202,203],{"class":72,"line":97},[70,204,206],{"emptyLinePlaceholder":205},true,"\n",[70,208,209],{"class":72,"line":103},[70,210,211],{},"let integer = Point { x: 5, y: 10 };\n",[70,213,214],{"class":72,"line":109},[70,215,216],{},"let float = Point { x: 1.0, y: 4.0 };\n",[24,218,219,220,223,224,227],{},"枚举同样支持泛型，标准库中的 ",[54,221,222],{},"Option\u003CT>"," 和 ",[54,225,226],{},"Result\u003CT, E>"," 就是最典型的例子。可以用多个泛型参数表示不同类型的字段：",[62,229,231],{"className":64,"code":230,"language":12,"meta":66,"style":66},"struct Pair\u003CT, U> {\n    a: T,\n    b: U,\n}\n",[54,232,233,238,243,248],{"__ignoreMap":66},[70,234,235],{"class":72,"line":73},[70,236,237],{},"struct Pair\u003CT, U> {\n",[70,239,240],{"class":72,"line":79},[70,241,242],{},"    a: T,\n",[70,244,245],{"class":72,"line":85},[70,246,247],{},"    b: U,\n",[70,249,250],{"class":72,"line":91},[70,251,124],{},[47,253,254],{"id":254},"方法中使用泛型",[24,256,257,258,261],{},"为泛型类型实现方法时，需要在 ",[54,259,260],{},"impl"," 后声明泛型参数：",[62,263,265],{"className":64,"code":264,"language":12,"meta":66,"style":66},"impl\u003CT> Point\u003CT> {\n    fn x(&self) -> &T {\n        &self.x\n    }\n}\n",[54,266,267,272,277,282,286],{"__ignoreMap":66},[70,268,269],{"class":72,"line":73},[70,270,271],{},"impl\u003CT> Point\u003CT> {\n",[70,273,274],{"class":72,"line":79},[70,275,276],{},"    fn x(&self) -> &T {\n",[70,278,279],{"class":72,"line":85},[70,280,281],{},"        &self.x\n",[70,283,284],{"class":72,"line":91},[70,285,112],{},[70,287,288],{"class":72,"line":97},[70,289,124],{},[24,291,292,293,296,297,300],{},"可以针对特定类型或满足特定约束的类型单独实现方法。例如，只有 ",[54,294,295],{},"Point\u003Cf64>"," 才提供 ",[54,298,299],{},"distance_from_origin","：",[62,302,304],{"className":64,"code":303,"language":12,"meta":66,"style":66},"impl Point\u003Cf64> {\n    fn distance_from_origin(&self) -> f64 {\n        (self.x.powi(2) + self.y.powi(2)).sqrt()\n    }\n}\n",[54,305,306,311,316,321,325],{"__ignoreMap":66},[70,307,308],{"class":72,"line":73},[70,309,310],{},"impl Point\u003Cf64> {\n",[70,312,313],{"class":72,"line":79},[70,314,315],{},"    fn distance_from_origin(&self) -> f64 {\n",[70,317,318],{"class":72,"line":85},[70,319,320],{},"        (self.x.powi(2) + self.y.powi(2)).sqrt()\n",[70,322,323],{"class":72,"line":91},[70,324,112],{},[70,326,327],{"class":72,"line":97},[70,328,124],{},[24,330,331,332,334],{},"也可以在 ",[54,333,260],{}," 上附加 trait 约束，使得方法对所有满足约束的类型可用：",[62,336,338],{"className":64,"code":337,"language":12,"meta":66,"style":66},"impl\u003CT: Display + PartialOrd> Point\u003CT> {\n    fn cmp_display(&self) {\n        if self.x >= self.y {\n            println!(\"x = {}\", self.x);\n        } else {\n            println!(\"y = {}\", self.y);\n        }\n    }\n}\n",[54,339,340,345,350,355,360,365,370,374,378],{"__ignoreMap":66},[70,341,342],{"class":72,"line":73},[70,343,344],{},"impl\u003CT: Display + PartialOrd> Point\u003CT> {\n",[70,346,347],{"class":72,"line":79},[70,348,349],{},"    fn cmp_display(&self) {\n",[70,351,352],{"class":72,"line":85},[70,353,354],{},"        if self.x >= self.y {\n",[70,356,357],{"class":72,"line":91},[70,358,359],{},"            println!(\"x = {}\", self.x);\n",[70,361,362],{"class":72,"line":97},[70,363,364],{},"        } else {\n",[70,366,367],{"class":72,"line":103},[70,368,369],{},"            println!(\"y = {}\", self.y);\n",[70,371,372],{"class":72,"line":109},[70,373,106],{},[70,375,376],{"class":72,"line":115},[70,377,112],{},[70,379,380],{"class":72,"line":121},[70,381,124],{},[47,383,44],{"id":44},[24,385,386,387,390,391,394,395,398],{},"调用泛型代码时，编译器为每一个使用的具体类型生成一份专用的副本，这个过程叫单态化。例如 ",[54,388,389],{},"largest(&[1, 2, 3])"," 会被编译为一份处理 ",[54,392,393],{},"i32"," 的 ",[54,396,397],{},"largest"," 函数，与手写非泛型函数拥有相同的性能。代价是编译时间增加，且可能产生更大的二进制文件。",[47,400,401],{"id":401},"泛型参数默认类型",[24,403,404,405,408],{},"在 trait 中定义泛型参数时，可以指定默认具体类型，减少显式标注。典型例子是标准库的 ",[54,406,407],{},"Add"," trait：",[62,410,412],{"className":64,"code":411,"language":12,"meta":66,"style":66},"trait Add\u003CRhs=Self> {\n    type Output;\n    fn add(self, rhs: Rhs) -> Self::Output;\n}\n",[54,413,414,419,424,429],{"__ignoreMap":66},[70,415,416],{"class":72,"line":73},[70,417,418],{},"trait Add\u003CRhs=Self> {\n",[70,420,421],{"class":72,"line":79},[70,422,423],{},"    type Output;\n",[70,425,426],{"class":72,"line":85},[70,427,428],{},"    fn add(self, rhs: Rhs) -> Self::Output;\n",[70,430,431],{"class":72,"line":91},[70,432,124],{},[24,434,435,436,439,440,443,444,447,448,450],{},"当写 ",[54,437,438],{},"a + b"," 时，如果没有显式指定 ",[54,441,442],{},"Rhs","，默认就是 ",[54,445,446],{},"Self","，即同类型相加。但你可以实现不同 ",[54,449,442],{}," 来实现异类型相加。",[34,452,454],{"id":453},"_62-trait特质","6.2 Trait（特质）",[24,456,457],{},"trait 是 Rust 中的共享行为抽象，告诉编译器不同类型共同拥有的功能。它类似于其他语言中的接口，但更强大。",[47,459,461],{"id":460},"定义-trait","定义 trait",[24,463,464,465,468],{},"定义一个 ",[54,466,467],{},"Summary"," trait，包含一个方法签名，也可带默认实现：",[62,470,472],{"className":64,"code":471,"language":12,"meta":66,"style":66},"pub trait Summary {\n    fn summarize(&self) -> String;\n}\n",[54,473,474,479,484],{"__ignoreMap":66},[70,475,476],{"class":72,"line":73},[70,477,478],{},"pub trait Summary {\n",[70,480,481],{"class":72,"line":79},[70,482,483],{},"    fn summarize(&self) -> String;\n",[70,485,486],{"class":72,"line":85},[70,487,124],{},[24,489,490],{},"也可以提供默认方法体，实现者可用也可覆写：",[62,492,494],{"className":64,"code":493,"language":12,"meta":66,"style":66},"pub trait Summary {\n    fn summarize(&self) -> String {\n        String::from(\"(Read more...)\")\n    }\n}\n",[54,495,496,500,505,510,514],{"__ignoreMap":66},[70,497,498],{"class":72,"line":73},[70,499,478],{},[70,501,502],{"class":72,"line":79},[70,503,504],{},"    fn summarize(&self) -> String {\n",[70,506,507],{"class":72,"line":85},[70,508,509],{},"        String::from(\"(Read more...)\")\n",[70,511,512],{"class":72,"line":91},[70,513,112],{},[70,515,516],{"class":72,"line":97},[70,517,124],{},[47,519,521],{"id":520},"实现-trait","实现 trait",[24,523,524,525,300],{},"为某个类型实现 trait 的语法是 ",[54,526,527],{},"impl Trait for Type",[62,529,531],{"className":64,"code":530,"language":12,"meta":66,"style":66},"pub struct NewsArticle {\n    pub headline: String,\n    pub content: String,\n}\n\nimpl Summary for NewsArticle {\n    fn summarize(&self) -> String {\n        format!(\"{}: {}\", self.headline, &self.content[..100])\n    }\n}\n",[54,532,533,538,543,548,552,556,561,565,570,574],{"__ignoreMap":66},[70,534,535],{"class":72,"line":73},[70,536,537],{},"pub struct NewsArticle {\n",[70,539,540],{"class":72,"line":79},[70,541,542],{},"    pub headline: String,\n",[70,544,545],{"class":72,"line":85},[70,546,547],{},"    pub content: String,\n",[70,549,550],{"class":72,"line":91},[70,551,124],{},[70,553,554],{"class":72,"line":97},[70,555,206],{"emptyLinePlaceholder":205},[70,557,558],{"class":72,"line":103},[70,559,560],{},"impl Summary for NewsArticle {\n",[70,562,563],{"class":72,"line":109},[70,564,504],{},[70,566,567],{"class":72,"line":115},[70,568,569],{},"        format!(\"{}: {}\", self.headline, &self.content[..100])\n",[70,571,572],{"class":72,"line":121},[70,573,112],{},[70,575,577],{"class":72,"line":576},10,[70,578,124],{},[47,580,581],{"id":581},"孤儿规则",[24,583,584,585,587],{},"Rust 的 trait 实现受",[42,586,581],{},"限制：如果要实现一个 trait 或为某个类型实现 trait，至少其中一个必须在当前 crate 中定义。这防止了上游 crate 添加新 trait 实现后破坏下游代码。换句话说，不能同时为外部类型实现外部 trait。",[24,589,590,591,594],{},"要绕开这一限制，可以使用",[42,592,593],{},"新类型模式","（newtype pattern），在后文介绍。",[47,596,598],{"id":597},"trait-作为参数","trait 作为参数",[24,600,601,602,605],{},"可以用 ",[54,603,604],{},"impl Trait"," 语法或 trait bound 语法指定要求参数的 trait。",[24,607,608,610],{},[54,609,604],{}," 形式：",[62,612,614],{"className":64,"code":613,"language":12,"meta":66,"style":66},"fn notify(item: &impl Summary) {\n    println!(\"{}\", item.summarize());\n}\n",[54,615,616,621,626],{"__ignoreMap":66},[70,617,618],{"class":72,"line":73},[70,619,620],{},"fn notify(item: &impl Summary) {\n",[70,622,623],{"class":72,"line":79},[70,624,625],{},"    println!(\"{}\", item.summarize());\n",[70,627,628],{"class":72,"line":85},[70,629,124],{},[24,631,632],{},"trait bound 形式（显式泛型）：",[62,634,636],{"className":64,"code":635,"language":12,"meta":66,"style":66},"fn notify\u003CT: Summary>(item: &T) {\n    println!(\"{}\", item.summarize());\n}\n",[54,637,638,643,647],{"__ignoreMap":66},[70,639,640],{"class":72,"line":73},[70,641,642],{},"fn notify\u003CT: Summary>(item: &T) {\n",[70,644,645],{"class":72,"line":79},[70,646,625],{},[70,648,649],{"class":72,"line":85},[70,650,124],{},[24,652,653,654,656],{},"当参数类型复杂时，",[54,655,604],{}," 更简洁；当需要多个参数为同一类型或复杂泛型关系时，trait bound 更合适。",[47,658,660],{"id":659},"trait-作为返回值","trait 作为返回值",[24,662,663],{},"可以让函数返回某个实现了指定 trait 的类型，而不暴露具体类型：",[62,665,667],{"className":64,"code":666,"language":12,"meta":66,"style":66},"fn returns_summarizable() -> impl Summary {\n    NewsArticle {\n        headline: String::from(\"Breaking News\"),\n        content: String::from(\"Something happened...\"),\n    }\n}\n",[54,668,669,674,679,684,689,693],{"__ignoreMap":66},[70,670,671],{"class":72,"line":73},[70,672,673],{},"fn returns_summarizable() -> impl Summary {\n",[70,675,676],{"class":72,"line":79},[70,677,678],{},"    NewsArticle {\n",[70,680,681],{"class":72,"line":85},[70,682,683],{},"        headline: String::from(\"Breaking News\"),\n",[70,685,686],{"class":72,"line":91},[70,687,688],{},"        content: String::from(\"Something happened...\"),\n",[70,690,691],{"class":72,"line":97},[70,692,112],{},[70,694,695],{"class":72,"line":103},[70,696,124],{},[24,698,699,700,702,703,706],{},"注意：",[54,701,604],{}," 在返回值位置时，函数只能返回",[42,704,705],{},"单一具体类型","，不能根据条件返回不同的实现类型。如果确实需要不同具体类型，就得使用 trait 对象。",[47,708,710,713],{"id":709},"dyn-traittrait-对象",[54,711,712],{},"dyn Trait","：trait 对象",[24,715,716,717,720,721,300],{},"trait 对象用于动态分发，即运行时决定具体方法。类型写作 ",[54,718,719],{},"&dyn Trait"," 或 ",[54,722,723],{},"Box\u003Cdyn Trait>",[62,725,727],{"className":64,"code":726,"language":12,"meta":66,"style":66},"fn notify(item: &dyn Summary) {\n    println!(\"{}\", item.summarize());\n}\n\nlet article = NewsArticle { ... };\nnotify(&article);\n",[54,728,729,734,738,742,746,751],{"__ignoreMap":66},[70,730,731],{"class":72,"line":73},[70,732,733],{},"fn notify(item: &dyn Summary) {\n",[70,735,736],{"class":72,"line":79},[70,737,625],{},[70,739,740],{"class":72,"line":85},[70,741,124],{},[70,743,744],{"class":72,"line":91},[70,745,206],{"emptyLinePlaceholder":205},[70,747,748],{"class":72,"line":97},[70,749,750],{},"let article = NewsArticle { ... };\n",[70,752,753],{"class":72,"line":103},[70,754,755],{},"notify(&article);\n",[24,757,758,759,762,763,765],{},"不同于静态分发的泛型，使用 trait 对象会有小幅运行时开销（虚表查找），且对象的大小在编译期未知，因此通常放在指针后。trait 对象要求使用的 trait 必须是",[42,760,761],{},"对象安全","的，即其方法不能返回 ",[54,764,446],{}," 类型、不能有泛型参数（除了关联类型受某些限制等）。",[47,767,768],{"id":768},"关联类型",[24,770,771,772,408],{},"关联类型是在 trait 定义中设定的类型占位符，具体类型由实现者指定。它们简化了复杂的泛型 trait 签名。最经典的例子是 ",[54,773,774],{},"Iterator",[62,776,778],{"className":64,"code":777,"language":12,"meta":66,"style":66},"pub trait Iterator {\n    type Item;\n    fn next(&mut self) -> Option\u003CSelf::Item>;\n}\n",[54,779,780,785,790,795],{"__ignoreMap":66},[70,781,782],{"class":72,"line":73},[70,783,784],{},"pub trait Iterator {\n",[70,786,787],{"class":72,"line":79},[70,788,789],{},"    type Item;\n",[70,791,792],{"class":72,"line":85},[70,793,794],{},"    fn next(&mut self) -> Option\u003CSelf::Item>;\n",[70,796,797],{"class":72,"line":91},[70,798,124],{},[24,800,801,802,805],{},"实现时指定 ",[54,803,804],{},"Item"," 具体类型：",[62,807,809],{"className":64,"code":808,"language":12,"meta":66,"style":66},"impl Iterator for Counter {\n    type Item = u32;\n    fn next(&mut self) -> Option\u003CSelf::Item> { ... }\n}\n",[54,810,811,816,821,826],{"__ignoreMap":66},[70,812,813],{"class":72,"line":73},[70,814,815],{},"impl Iterator for Counter {\n",[70,817,818],{"class":72,"line":79},[70,819,820],{},"    type Item = u32;\n",[70,822,823],{"class":72,"line":85},[70,824,825],{},"    fn next(&mut self) -> Option\u003CSelf::Item> { ... }\n",[70,827,828],{"class":72,"line":91},[70,829,124],{},[24,831,832,833,835,836,839],{},"关联类型使 ",[54,834,774],{}," 不需要像 ",[54,837,838],{},"Iterator\u003CItem=T>"," 那样每次都要标注泛型，接口更干净。",[34,841,843],{"id":842},"_63-常用标准-trait","6.3 常用标准 Trait",[24,845,846],{},"Rust 标准库提供了一系列基础 trait，它们是类型系统进行数据操作和生态互操作的基石。",[47,848,850,851,854,855],{"id":849},"格式化display-与-debug","格式化：",[54,852,853],{},"Display"," 与 ",[54,856,857],{},"Debug",[859,860,861,875],"ul",{},[862,863,864,866,867,870,871,874],"li",{},[54,865,857],{},"：面向开发者的调试输出，",[54,868,869],{},"{:?}"," 格式串使用。通常通过 ",[54,872,873],{},"#[derive(Debug)]"," 自动生成。",[862,876,877,879,880,883,884,887],{},[54,878,853],{},"：面向用户的格式化输出，",[54,881,882],{},"{}"," 使用，需要手动实现 ",[54,885,886],{},"fmt"," 方法。",[62,889,891],{"className":64,"code":890,"language":12,"meta":66,"style":66},"use std::fmt;\n\nimpl fmt::Display for Point {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"({}, {})\", self.x, self.y)\n    }\n}\n",[54,892,893,898,902,907,912,917,921],{"__ignoreMap":66},[70,894,895],{"class":72,"line":73},[70,896,897],{},"use std::fmt;\n",[70,899,900],{"class":72,"line":79},[70,901,206],{"emptyLinePlaceholder":205},[70,903,904],{"class":72,"line":85},[70,905,906],{},"impl fmt::Display for Point {\n",[70,908,909],{"class":72,"line":91},[70,910,911],{},"    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n",[70,913,914],{"class":72,"line":97},[70,915,916],{},"        write!(f, \"({}, {})\", self.x, self.y)\n",[70,918,919],{"class":72,"line":103},[70,920,112],{},[70,922,923],{"class":72,"line":109},[70,924,124],{},[47,926,928,854,931],{"id":927},"clone-与-copy",[54,929,930],{},"Clone",[54,932,933],{},"Copy",[859,935,936,944],{},[862,937,938,940,941,887],{},[54,939,930],{},"：显式深拷贝，调用 ",[54,942,943],{},".clone()",[862,945,946,948,949,952],{},[54,947,933],{},"：隐式浅拷贝（按位复制），标记类型，要求类型不涉及资源所有权。简单的标量、无分配的聚合类型通常派生 ",[54,950,951],{},"Copy, Clone","。",[62,954,956],{"className":64,"code":955,"language":12,"meta":66,"style":66},"#[derive(Copy, Clone)]\nstruct Color { r: u8, g: u8, b: u8 }\n",[54,957,958,963],{"__ignoreMap":66},[70,959,960],{"class":72,"line":73},[70,961,962],{},"#[derive(Copy, Clone)]\n",[70,964,965],{"class":72,"line":79},[70,966,967],{},"struct Color { r: u8, g: u8, b: u8 }\n",[24,969,970,971,973,974,952],{},"实现 ",[54,972,933],{}," 必须同时实现 ",[54,975,930],{},[47,977,979,980,983,984,854,987,983,990],{"id":978},"比较partialeq-eq-与-partialord-ord","比较：",[54,981,982],{},"PartialEq"," \u002F ",[54,985,986],{},"Eq",[54,988,989],{},"PartialOrd",[54,991,992],{},"Ord",[859,994,995,1013,1022,1035],{},[862,996,997,999,1000,394,1003,1006,1007,223,1010,952],{},[54,998,982],{},"：允许部分等价关系（如 ",[54,1001,1002],{},"f64",[54,1004,1005],{},"NaN != NaN","），提供 ",[54,1008,1009],{},"==",[54,1011,1012],{},"!=",[862,1014,1015,1017,1018,1021],{},[54,1016,986],{},"：标记 trait，表示等价关系完全，无部分性。通常也通过 ",[54,1019,1020],{},"derive"," 实现。",[862,1023,1024,1026,1027,1030,1031,1034],{},[54,1025,989],{},"：部分顺序，提供 ",[54,1028,1029],{},"\u003C","、",[54,1032,1033],{},">"," 等。",[862,1036,1037,1039],{},[54,1038,992],{},"：全序关系，要求类型形成严格的全序。",[47,1041,1043],{"id":1042},"hash",[54,1044,1045],{},"Hash",[24,1047,970,1048,1050,1051,1054,1055,1057,1058,952],{},[54,1049,1045],{}," 的类型可被哈希，用于 ",[54,1052,1053],{},"HashMap"," 的键。可以通过 ",[54,1056,1020],{}," 自动生成，只要所有字段都实现 ",[54,1059,1045],{},[47,1061,1063],{"id":1062},"default",[54,1064,1065],{},"Default",[24,1067,1068,1069,1072,1073,1075],{},"提供类型的默认值。很多集合（如 ",[54,1070,1071],{},"Vec","）使用 ",[54,1074,1065],{}," 来初始化。",[62,1077,1079],{"className":64,"code":1078,"language":12,"meta":66,"style":66},"#[derive(Default)]\nstruct Config {\n    port: u16,\n    debug: bool,\n}\nlet config = Config { port: 8080, ..Default::default() };\n",[54,1080,1081,1086,1091,1096,1101,1105],{"__ignoreMap":66},[70,1082,1083],{"class":72,"line":73},[70,1084,1085],{},"#[derive(Default)]\n",[70,1087,1088],{"class":72,"line":79},[70,1089,1090],{},"struct Config {\n",[70,1092,1093],{"class":72,"line":85},[70,1094,1095],{},"    port: u16,\n",[70,1097,1098],{"class":72,"line":91},[70,1099,1100],{},"    debug: bool,\n",[70,1102,1103],{"class":72,"line":97},[70,1104,124],{},[70,1106,1107],{"class":72,"line":103},[70,1108,1109],{},"let config = Config { port: 8080, ..Default::default() };\n",[47,1111,1113,983,1116],{"id":1112},"from-into",[54,1114,1115],{},"From",[54,1117,1118],{},"Into",[24,1120,1121,1122,1125,1126,1129,1130,1132,1133,1135],{},"类型转换 trait。实现了 ",[54,1123,1124],{},"From\u003CA> for B","，会自动得到 ",[54,1127,1128],{},"Into\u003CB> for A","。推荐手动实现 ",[54,1131,1115],{},"，因为 ",[54,1134,1118],{}," 由标准库通用实现自动生成。",[62,1137,1139],{"className":64,"code":1138,"language":12,"meta":66,"style":66},"impl From\u003Ci32> for MyNumber {\n    fn from(val: i32) -> Self {\n        MyNumber(val)\n    }\n}\nlet num: MyNumber = 42.into();\n",[54,1140,1141,1146,1151,1156,1160,1164],{"__ignoreMap":66},[70,1142,1143],{"class":72,"line":73},[70,1144,1145],{},"impl From\u003Ci32> for MyNumber {\n",[70,1147,1148],{"class":72,"line":79},[70,1149,1150],{},"    fn from(val: i32) -> Self {\n",[70,1152,1153],{"class":72,"line":85},[70,1154,1155],{},"        MyNumber(val)\n",[70,1157,1158],{"class":72,"line":91},[70,1159,112],{},[70,1161,1162],{"class":72,"line":97},[70,1163,124],{},[70,1165,1166],{"class":72,"line":103},[70,1167,1168],{},"let num: MyNumber = 42.into();\n",[24,1170,1171,1174,1175,1177],{},[54,1172,1173],{},"?"," 运算符在错误传播时也依赖 ",[54,1176,1115],{}," 来转换错误类型。",[47,1179,1181,983,1184],{"id":1180},"deref-derefmut",[54,1182,1183],{},"Deref",[54,1185,1186],{},"DerefMut",[24,1188,1189,1190,952,1193,1195,1196,1198],{},"实现解引用操作符 ",[54,1191,1192],{},"*",[54,1194,1183],{}," 让智能指针能当普通引用来使用；",[54,1197,1186],{}," 用于可变解引用。过度使用可能破坏封装性，主要应用在智能指针类型上。",[62,1200,1202],{"className":64,"code":1201,"language":12,"meta":66,"style":66},"impl\u003CT> Deref for MyBox\u003CT> {\n    type Target = T;\n    fn deref(&self) -> &Self::Target {\n        &self.data\n    }\n}\n",[54,1203,1204,1209,1214,1219,1224,1228],{"__ignoreMap":66},[70,1205,1206],{"class":72,"line":73},[70,1207,1208],{},"impl\u003CT> Deref for MyBox\u003CT> {\n",[70,1210,1211],{"class":72,"line":79},[70,1212,1213],{},"    type Target = T;\n",[70,1215,1216],{"class":72,"line":85},[70,1217,1218],{},"    fn deref(&self) -> &Self::Target {\n",[70,1220,1221],{"class":72,"line":91},[70,1222,1223],{},"        &self.data\n",[70,1225,1226],{"class":72,"line":97},[70,1227,112],{},[70,1229,1230],{"class":72,"line":103},[70,1231,124],{},[47,1233,1235],{"id":1234},"drop",[54,1236,1237],{},"Drop",[24,1239,1240,1241,1243,1244,1247],{},"析构器，值离开作用域时会自动调用 ",[54,1242,1234],{}," 方法，用于释放资源、关闭文件等。不能手动调用，但可以用 ",[54,1245,1246],{},"std::mem::drop"," 提前转移所有权并触发析构。",[62,1249,1251],{"className":64,"code":1250,"language":12,"meta":66,"style":66},"impl Drop for CustomSmartPointer {\n    fn drop(&mut self) {\n        println!(\"Dropping!\");\n    }\n}\n",[54,1252,1253,1258,1263,1268,1272],{"__ignoreMap":66},[70,1254,1255],{"class":72,"line":73},[70,1256,1257],{},"impl Drop for CustomSmartPointer {\n",[70,1259,1260],{"class":72,"line":79},[70,1261,1262],{},"    fn drop(&mut self) {\n",[70,1264,1265],{"class":72,"line":85},[70,1266,1267],{},"        println!(\"Dropping!\");\n",[70,1269,1270],{"class":72,"line":91},[70,1271,112],{},[70,1273,1274],{"class":72,"line":97},[70,1275,124],{},[47,1277,1279],{"id":1278},"iterator",[54,1280,774],{},[24,1282,1283,1284,1286,1287,1030,1290,1030,1293,1296,1297,1300,1301,1303],{},"迭代器的核心 trait，实现了 ",[54,1285,774],{}," 的类型就能使用 ",[54,1288,1289],{},"map",[54,1291,1292],{},"filter",[54,1294,1295],{},"collect"," 等一整套适配器方法。只需要实现 ",[54,1298,1299],{},"next"," 方法，关联类型 ",[54,1302,804],{}," 指定迭代出的元素类型。",[62,1305,1307],{"className":64,"code":1306,"language":12,"meta":66,"style":66},"struct Counter { count: u32 }\nimpl Iterator for Counter {\n    type Item = u32;\n    fn next(&mut self) -> Option\u003CSelf::Item> {\n        self.count += 1;\n        if self.count \u003C 6 { Some(self.count) } else { None }\n    }\n}\n",[54,1308,1309,1314,1318,1322,1327,1332,1337,1341],{"__ignoreMap":66},[70,1310,1311],{"class":72,"line":73},[70,1312,1313],{},"struct Counter { count: u32 }\n",[70,1315,1316],{"class":72,"line":79},[70,1317,815],{},[70,1319,1320],{"class":72,"line":85},[70,1321,820],{},[70,1323,1324],{"class":72,"line":91},[70,1325,1326],{},"    fn next(&mut self) -> Option\u003CSelf::Item> {\n",[70,1328,1329],{"class":72,"line":97},[70,1330,1331],{},"        self.count += 1;\n",[70,1333,1334],{"class":72,"line":103},[70,1335,1336],{},"        if self.count \u003C 6 { Some(self.count) } else { None }\n",[70,1338,1339],{"class":72,"line":109},[70,1340,112],{},[70,1342,1343],{"class":72,"line":115},[70,1344,124],{},[24,1346,1347],{},"标准库为所有迭代器提供了大量可用方法，零成本抽象。",[34,1349,1351],{"id":1350},"_64-高级-trait","6.4 高级 Trait",[47,1353,1355],{"id":1354},"supertrait超-trait","Supertrait（超 trait）",[24,1357,1358,1359,1362,1363,1366,1367,952],{},"一个 trait 可能依赖于另一个 trait 的功能，此时可以使用超 trait 语法 ",[54,1360,1361],{},"trait Foo: Bar"," 表示实现 ",[54,1364,1365],{},"Foo"," 的类型必须同时实现 ",[54,1368,1369],{},"Bar",[62,1371,1373],{"className":64,"code":1372,"language":12,"meta":66,"style":66},"trait OutlinePrint: fmt::Display {\n    fn outline_print(&self) {\n        let output = self.to_string();\n        println!(\"{}\", \"*\".repeat(output.len() + 4));\n        println!(\"*{}*\", \" \".repeat(output.len() + 2));\n        println!(\"* {} *\", output);\n        println!(\"*{}*\", \" \".repeat(output.len() + 2));\n        println!(\"{}\", \"*\".repeat(output.len() + 4));\n    }\n}\n",[54,1374,1375,1380,1385,1390,1395,1400,1405,1409,1413,1417],{"__ignoreMap":66},[70,1376,1377],{"class":72,"line":73},[70,1378,1379],{},"trait OutlinePrint: fmt::Display {\n",[70,1381,1382],{"class":72,"line":79},[70,1383,1384],{},"    fn outline_print(&self) {\n",[70,1386,1387],{"class":72,"line":85},[70,1388,1389],{},"        let output = self.to_string();\n",[70,1391,1392],{"class":72,"line":91},[70,1393,1394],{},"        println!(\"{}\", \"*\".repeat(output.len() + 4));\n",[70,1396,1397],{"class":72,"line":97},[70,1398,1399],{},"        println!(\"*{}*\", \" \".repeat(output.len() + 2));\n",[70,1401,1402],{"class":72,"line":103},[70,1403,1404],{},"        println!(\"* {} *\", output);\n",[70,1406,1407],{"class":72,"line":109},[70,1408,1399],{},[70,1410,1411],{"class":72,"line":115},[70,1412,1394],{},[70,1414,1415],{"class":72,"line":121},[70,1416,112],{},[70,1418,1419],{"class":72,"line":576},[70,1420,124],{},[24,1422,1423,1424,1427,1428,1431,1432,952],{},"这样 ",[54,1425,1426],{},"OutlinePrint"," 的方法就可以调用 ",[54,1429,1430],{},"self.to_string()","，因为它要求 ",[54,1433,853],{},[47,1435,1436],{"id":1436},"完全限定语法",[24,1438,1439],{},"当多个 trait 或类型自身拥有同名方法时，需要使用完全限定语法消除歧义：",[62,1441,1443],{"className":64,"code":1442,"language":12,"meta":66,"style":66},"\u003CType as Trait>::function(receiver_if_method, args...);\n",[54,1444,1445],{"__ignoreMap":66},[70,1446,1447],{"class":72,"line":73},[70,1448,1442],{},[24,1450,1451],{},"例如，一个类型同时实现了两个有同名方法的 trait：",[62,1453,1455],{"className":64,"code":1454,"language":12,"meta":66,"style":66},"trait Pilot { fn fly(&self); }\ntrait Wizard { fn fly(&self); }\nstruct Human;\n\nimpl Pilot for Human {\n    fn fly(&self) { println!(\"Captain speaking.\"); }\n}\nimpl Wizard for Human {\n    fn fly(&self) { println!(\"Up!\"); }\n}\nimpl Human {\n    fn fly(&self) { println!(\"Waving arms.\"); }\n}\n\nlet person = Human;\nperson.fly();                 \u002F\u002F 调用 Human 自身方法\nPilot::fly(&person);          \u002F\u002F 调用 Pilot trait 方法\nWizard::fly(&person);         \u002F\u002F 调用 Wizard trait 方法\n",[54,1456,1457,1462,1467,1472,1476,1481,1486,1490,1495,1500,1504,1510,1516,1521,1526,1532,1538,1544],{"__ignoreMap":66},[70,1458,1459],{"class":72,"line":73},[70,1460,1461],{},"trait Pilot { fn fly(&self); }\n",[70,1463,1464],{"class":72,"line":79},[70,1465,1466],{},"trait Wizard { fn fly(&self); }\n",[70,1468,1469],{"class":72,"line":85},[70,1470,1471],{},"struct Human;\n",[70,1473,1474],{"class":72,"line":91},[70,1475,206],{"emptyLinePlaceholder":205},[70,1477,1478],{"class":72,"line":97},[70,1479,1480],{},"impl Pilot for Human {\n",[70,1482,1483],{"class":72,"line":103},[70,1484,1485],{},"    fn fly(&self) { println!(\"Captain speaking.\"); }\n",[70,1487,1488],{"class":72,"line":109},[70,1489,124],{},[70,1491,1492],{"class":72,"line":115},[70,1493,1494],{},"impl Wizard for Human {\n",[70,1496,1497],{"class":72,"line":121},[70,1498,1499],{},"    fn fly(&self) { println!(\"Up!\"); }\n",[70,1501,1502],{"class":72,"line":576},[70,1503,124],{},[70,1505,1507],{"class":72,"line":1506},11,[70,1508,1509],{},"impl Human {\n",[70,1511,1513],{"class":72,"line":1512},12,[70,1514,1515],{},"    fn fly(&self) { println!(\"Waving arms.\"); }\n",[70,1517,1519],{"class":72,"line":1518},13,[70,1520,124],{},[70,1522,1524],{"class":72,"line":1523},14,[70,1525,206],{"emptyLinePlaceholder":205},[70,1527,1529],{"class":72,"line":1528},15,[70,1530,1531],{},"let person = Human;\n",[70,1533,1535],{"class":72,"line":1534},16,[70,1536,1537],{},"person.fly();                 \u002F\u002F 调用 Human 自身方法\n",[70,1539,1541],{"class":72,"line":1540},17,[70,1542,1543],{},"Pilot::fly(&person);          \u002F\u002F 调用 Pilot trait 方法\n",[70,1545,1547],{"class":72,"line":1546},18,[70,1548,1549],{},"Wizard::fly(&person);         \u002F\u002F 调用 Wizard trait 方法\n",[24,1551,1552,1553,1556],{},"对于关联函数（无 self），需要用 ",[54,1554,1555],{},"\u003CHuman as Wizard>::fly()"," 形式。",[47,1558,1560],{"id":1559},"新类型模式newtype-pattern","新类型模式（newtype pattern）",[24,1562,1563],{},"孤儿规则阻止我们为外部类型实现外部 trait。新类型模式通过定义一个元组结构体包装外部类型，使它能获得本地的身份，从而可以安全地实现外部 trait。",[62,1565,1567],{"className":64,"code":1566,"language":12,"meta":66,"style":66},"struct Wrapper(Vec\u003CString>);\n\nimpl fmt::Display for Wrapper {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"[{}]\", self.0.join(\", \"))\n    }\n}\n",[54,1568,1569,1574,1578,1583,1587,1592,1596],{"__ignoreMap":66},[70,1570,1571],{"class":72,"line":73},[70,1572,1573],{},"struct Wrapper(Vec\u003CString>);\n",[70,1575,1576],{"class":72,"line":79},[70,1577,206],{"emptyLinePlaceholder":205},[70,1579,1580],{"class":72,"line":85},[70,1581,1582],{},"impl fmt::Display for Wrapper {\n",[70,1584,1585],{"class":72,"line":91},[70,1586,911],{},[70,1588,1589],{"class":72,"line":97},[70,1590,1591],{},"        write!(f, \"[{}]\", self.0.join(\", \"))\n",[70,1593,1594],{"class":72,"line":103},[70,1595,112],{},[70,1597,1598],{"class":72,"line":109},[70,1599,124],{},[24,1601,1602,1605,1606,1608,1609,1611],{},[54,1603,1604],{},"Wrapper"," 是本地类型，因此可以为它实现 ",[54,1607,853],{},"。使用时通过 ",[54,1610,1604],{}," 包装和解构访问内部值。",[47,1613,1615,1616,1619,1620,1619,1623,1619,1626],{"id":1614},"标记-traitsend-sync-sized-unpin","标记 trait：",[54,1617,1618],{},"Send",", ",[54,1621,1622],{},"Sync",[54,1624,1625],{},"Sized",[54,1627,1628],{},"Unpin",[24,1630,1631,1632,1635],{},"这些较为特殊的 trait 通常由编译器自动推导，或者在 ",[54,1633,1634],{},"unsafe"," 中手动实现。",[859,1637,1638,1652,1665,1678],{},[862,1639,1640,1644,1645,1647,1648,1651],{},[42,1641,1642],{},[54,1643,1618],{},"：类型的所有权可以安全地转移到另一个线程。大多数类型都是 ",[54,1646,1618],{},"，但 ",[54,1649,1650],{},"Rc\u003CT>"," 不是。",[862,1653,1654,1658,1659,1661,1662,1651],{},[42,1655,1656],{},[54,1657,1622],{},"：类型的共享引用可以安全地在多个线程间访问。基本类型是 ",[54,1660,1622],{},"，",[54,1663,1664],{},"RefCell\u003CT>",[862,1666,1667,1671,1672,1674,1675,952],{},[42,1668,1669],{},[54,1670,1625],{},"：编译期已知大小的类型。默认泛型参数有隐性 ",[54,1673,1625],{}," 约束，如果要放宽，可用 ",[54,1676,1677],{},"T: ?Sized",[862,1679,1680,1684,1685,1661,1687,1690],{},[42,1681,1682],{},[54,1683,1628],{},"：表示类型可以安全地在内存中移动而不破坏内部指针。大多数类型自动实现 ",[54,1686,1628],{},[54,1688,1689],{},"Pin"," 相关的内容用于异步编程和自引用结构体。",[24,1692,1693],{},"这些标记 trait 构成了 Rust 强大并发和内存安全保证的一部分，会在高级主题中进一步详细应用。",[34,1695,1696],{"id":1696},"参考文献",[24,1698,1699],{},"以下链接在编写时均可正常访问：",[1701,1702,1703,1716],"table",{},[1704,1705,1706],"thead",{},[1707,1708,1709,1713],"tr",{},[1710,1711,1712],"th",{},"资料",[1710,1714,1715],{},"说明",[1717,1718,1719,1733,1745],"tbody",{},[1707,1720,1721,1730],{},[1722,1723,1724],"td",{},[28,1725,1729],{"href":1726,"rel":1727},"https:\u002F\u002Fdoc.rust-lang.org\u002Fbook\u002Fch10-00-generics.html",[1728],"nofollow","泛型",[1722,1731,1732],{},"官方书第 10 章",[1707,1734,1735,1742],{},[1722,1736,1737],{},[28,1738,1741],{"href":1739,"rel":1740},"https:\u002F\u002Fdoc.rust-lang.org\u002Fbook\u002Fch10-02-traits.html",[1728],"Trait",[1722,1743,1744],{},"官方书",[1707,1746,1747,1754],{},[1722,1748,1749],{},[28,1750,1753],{"href":1751,"rel":1752},"https:\u002F\u002Fdoc.rust-lang.org\u002Freference\u002Ftraits.html",[1728],"Rust Reference · Traits",[1722,1755,1756],{},"参考",[1758,1759,1760],"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":66,"searchDepth":79,"depth":79,"links":1762},[1763,1770,1780,1796,1803],{"id":36,"depth":79,"text":37,"children":1764},[1765,1766,1767,1768,1769],{"id":49,"depth":85,"text":49},{"id":173,"depth":85,"text":173},{"id":254,"depth":85,"text":254},{"id":44,"depth":85,"text":44},{"id":401,"depth":85,"text":401},{"id":453,"depth":79,"text":454,"children":1771},[1772,1773,1774,1775,1776,1777,1779],{"id":460,"depth":85,"text":461},{"id":520,"depth":85,"text":521},{"id":581,"depth":85,"text":581},{"id":597,"depth":85,"text":598},{"id":659,"depth":85,"text":660},{"id":709,"depth":85,"text":1778},"dyn Trait：trait 对象",{"id":768,"depth":85,"text":768},{"id":842,"depth":79,"text":843,"children":1781},[1782,1784,1786,1788,1789,1790,1792,1794,1795],{"id":849,"depth":85,"text":1783},"格式化：Display 与 Debug",{"id":927,"depth":85,"text":1785},"Clone 与 Copy",{"id":978,"depth":85,"text":1787},"比较：PartialEq \u002F Eq 与 PartialOrd \u002F Ord",{"id":1042,"depth":85,"text":1045},{"id":1062,"depth":85,"text":1065},{"id":1112,"depth":85,"text":1791},"From \u002F Into",{"id":1180,"depth":85,"text":1793},"Deref \u002F DerefMut",{"id":1234,"depth":85,"text":1237},{"id":1278,"depth":85,"text":774},{"id":1350,"depth":79,"text":1351,"children":1797},[1798,1799,1800,1801],{"id":1354,"depth":85,"text":1355},{"id":1436,"depth":85,"text":1436},{"id":1559,"depth":85,"text":1560},{"id":1614,"depth":85,"text":1802},"标记 trait：Send, Sync, Sized, Unpin",{"id":1696,"depth":79,"text":1696},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FRust\u002Ft","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FRust\u002Ft.md","md",{"items":1809},[1810,1814,1818,1822,1826,1830],{"path":1811,"title":1812,"description":1813,"category":10,"score":103},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fdocs","第八章：测试、文档与质量","Rust 将测试和文档视为语言的一等公民。通过内置的测试框架，你可以在项目里编写单元测试、集成测试以及随文档一起运行的示例测试，三者共用 cargo test 命令。配合 cargo doc 生成文档，形成了一套确保代码质量与可维护性…",{"path":1815,"title":1816,"description":1817,"category":10,"score":103},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ftype","第二章：基础语法与类型","Rust 的类型系统和语法设计处处体现着“安全”与“显式”的理念。这一章你将掌握变量绑定、基本类型、复合类型、函数定义以及所有基础控制流结构，它们是你写出任何 Rust 程序的基石。",{"path":1819,"title":1820,"description":1821,"category":10,"score":103},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fpackage","第七章：模块系统与包管理","Rust 的模块系统为代码组织、封装和复用提供了一套严谨但灵活的机制。包、crate、模块以及 use 路径相互配合，让你能够把项目拆解成清晰的功能单元，同时精确控制哪些对外可见。本章将带你系统掌握这些构建大型 Rust 项目所必需的…",{"path":1823,"title":1824,"description":1825,"category":10,"score":103},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fother","第十章：进阶特性与模式","Rust 的核心安全保证覆盖了绝大多数日常编程场景。但当你需要打破常规——无论是编写极致通用的抽象、与 C 库交互，还是内联优化——本章将带你进入 Rust 的深层能力：声明宏与过程宏、unsafe 的超能力与封装、高级类型系统技巧…",{"path":1827,"title":1828,"description":1829,"category":10,"score":103},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ferror","第五章：错误处理","Rust 将错误明确分为两类：不可恢复的错误与可恢复的错误。通过 panic! 处理前一种，Result 处理后一种，这让程序的错误路径不再是隐式的控制流，而是强类型、必须处理的代码分支。配合 Option 对缺失值的处理以及丰富的组…",{"path":1831,"title":1832,"description":1833,"category":10,"score":103},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fcore","第三章：所有权、借用与生命周期（核心）","所有权系统是 Rust 最独特、最核心的语言特性。它让 Rust 无需垃圾回收器就能保证内存安全，并在编译期消除数据竞争。本章你将深入理解所有权如何运转、引用和借用如何被检查、生命周期如何标注，以及常见智能指针如何扩展所有权模型。",{"series":1835,"title":12,"items":1836,"index":115,"prev":1860,"next":1861},"booklet\u002Fend\u002Frust",[1837,1841,1843,1845,1849,1851,1853,1855,1857,1858],{"path":1838,"title":1839,"date":1840,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fasync","第九章：并发与异步","2020-05-22",{"path":30,"title":31,"date":1842,"pinned":15},"2020-07-21",{"path":1831,"title":1832,"date":1844,"pinned":15},"2023-05-09",{"path":1846,"title":1847,"date":1848,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fdata-type","第四章：复合数据类型","2021-02-24",{"path":1811,"title":1812,"date":1850,"pinned":15},"2026-01-11",{"path":1827,"title":1828,"date":1852,"pinned":15},"2023-11-03",{"path":1823,"title":1824,"date":1854,"pinned":15},"2023-12-29",{"path":1819,"title":1820,"date":1856,"pinned":15},"2024-05-26",{"path":7,"title":8,"date":14,"pinned":15},{"path":1815,"title":1816,"date":1859,"pinned":15},"2024-08-31",{"path":1819,"title":1820,"date":1856,"pinned":15},{"path":1815,"title":1816,"date":1859,"pinned":15}]