<!DOCTYPE HTML>  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< html  lang = "en" >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    < head > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < meta  charset = "UTF-8" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < title > Rust 程序设计语言 中文版< / title > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < meta  content = "text/html; charset=utf-8"  http-equiv = "Content-Type" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < meta  name = "description"  content = "Rust 程序设计语言 中文版" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < meta  name = "viewport"  content = "width=device-width, initial-scale=1" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < base  href = "" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < link  rel = "stylesheet"  href = "book.css" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < link  href = 'https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800'  rel = 'stylesheet'  type = 'text/css' > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < link  rel = "shortcut icon"  href = "favicon.png" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        <!--  Font Awesome  --> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < link  rel = "stylesheet"  href = "https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < link  rel = "stylesheet"  href = "highlight.css" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < link  rel = "stylesheet"  href = "tomorrow-night.css" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        <!--  MathJax  --> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < script  type = "text/javascript"  src = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" > < / script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        <!--  Fetch JQuery from CDN but have a local fallback  --> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < script  src = "https://code.jquery.com/jquery-2.1.4.min.js" > < / script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if (typeof jQuery == 'undefined') {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                document.write(unescape("%3Cscript src='jquery.js'%3E%3C/script%3E"));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < / script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    < / head > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    < body  class = "light" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        <!--  Set the theme before any content is loaded, prevents flash  --> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < script  type = "text/javascript" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            var theme = localStorage.getItem('theme');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if (theme == null) { theme = 'light'; }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            $('body').removeClass().addClass(theme);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < / script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        <!--  Hide / unhide sidebar before it is displayed  --> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < script  type = "text/javascript" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            var sidebar = localStorage.getItem('sidebar');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if (sidebar === "hidden") { $("html").addClass("sidebar-hidden") }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            else if (sidebar === "visible") { $("html").addClass("sidebar-visible") }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < / script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < div  id = "sidebar"  class = "sidebar" > 
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
									
										 
							
							
								            < ul  class = "chapter" > < li > < a  href = "ch01-00-introduction.html" > < strong > 1.< / strong >  介绍< / a > < / li > < li > < ul  class = "section" > < li > < a  href = "ch01-01-installation.html" > < strong > 1.1.< / strong >  安装< / a > < / li > < li > < a  href = "ch01-02-hello-world.html" > < strong > 1.2.< / strong >  Hello, World!< / a > < / li > < / ul > < / li > < li > < a  href = "ch02-00-guessing-game-tutorial.html" > < strong > 2.< / strong >  猜猜看教程< / a > < / li > < li > < a  href = "ch03-00-common-programming-concepts.html" > < strong > 3.< / strong >  通用编程概念< / a > < / li > < li > < ul  class = "section" > < li > < a  href = "ch03-01-variables-and-mutability.html" > < strong > 3.1.< / strong >  变量和可变性< / a > < / li > < li > < a  href = "ch03-02-data-types.html" > < strong > 3.2.< / strong >  数据类型< / a > < / li > < li > < a  href = "ch03-03-how-functions-work.html" > < strong > 3.3.< / strong >  函数如何工作< / a > < / li > < li > < a  href = "ch03-04-comments.html" > < strong > 3.4.< / strong >  注释< / a > < / li > < li > < a  href = "ch03-05-control-flow.html" > < strong > 3.5.< / strong >  控制流< / a > < / li > < / ul > < / li > < li > < a  href = "ch04-00-understanding-ownership.html" > < strong > 4.< / strong >  认识所有权< / a > < / li > < li > < ul  class = "section" > < li > < a  href = "ch04-01-what-is-ownership.html" > < strong > 4.1.< / strong >  什么是所有权< / a > < / li > < li > < a  href = "ch04-02-references-and-borrowing.html" > < strong > 4.2.< / strong >  引用 &  借用< / a > < / li > < li > < a  href = "ch04-03-slices.html" > < strong > 4.3.< / strong >  Slices< / a > < / li > < / ul > < / li > < li > < a  href = "ch05-00-structs.html" > < strong > 5.< / strong >  结构体< / a > < / li > < li > < ul  class = "section" > < li > < a  href = "ch05-01-method-syntax.html" > < strong > 5.1.< / strong >  方法语法< / a > < / li > < / ul > < / li > < li > < a  href = "ch06-00-enums.html" > < strong > 6.< / strong >  枚举和模式匹配< / a > < / li > < li > < ul  class = "section" > < li > < a  href = "ch06-01-defining-an-enum.html"  class = "active" > < strong > 6.1.< / strong >  定义枚举< / a > < / li > < li > < a  href = "ch06-02-match.html" > < strong > 6.2.< / strong >  < code > match< / code > 控制流运算符< / a > < / li > < li > < a  href = "ch06-03-if-let.html" > < strong > 6.3.< / strong >  < code > if let< / code > 简单控制流< / a > < / li > < / ul > < / li > < li > < a  href = "ch07-00-modules.html" > < strong > 7.< / strong >  模块< / a > < / li > < li > < ul  class = "section" > < li > < a  href = "ch07-01-mod-and-the-filesystem.html" > < strong > 7.1.< / strong >  < code > mod< / code > 和文件系统< / a > < / li > < li > < a  href = "ch07-02-controlling-visibility-with-pub.html" > < strong > 7.2.< / strong >  使用< code > pub< / code > 控制可见性< / a > < / li > < li > < a  href = "ch07-03-importing-names-with-use.html" > < strong > 7.3.< / strong >  使用< code > use< / code > 导入命名< / a > < / li > < / ul > < / li > < li > < a  href = "ch08-00-common-collections.html" > < strong > 8.< / strong >  通用集合类型< / a > < / li > < li > < ul  class = "section" > < li > < a  href = "ch08-01-vectors.html" > < strong > 8.1.< / strong >  vector< / a > < / li > < li > < a  href = "ch08-02-strings.html" > < strong > 8.2.< / strong >  字符串< / a > < / li > < li > < a  href = "ch08-03-hash-maps.html" > < strong > 8.3.< / strong >  哈希 map< / a > < / li > < / ul > < / li > < li > < a  href = "ch09-00-error-handling.html" > < strong > 9.< / strong >  错误处理< / a > < / li > < li > < ul  class = "section" > < li > < a  href = "ch09-01-unrecoverable-errors-with-panic.html" > < strong > 9.1.< / strong >  < code > panic!< / code > 与不可恢复的错误< / a > < / li > < li > < a  href = "ch09-02-recoverable-errors-with-result.html" > < strong > 9.2.< / strong >  < code > Result< / code > 与可恢复的错误< / a > < / li > < li > < a  href = "ch09-03-to-panic-or-not-to-panic.html" > < strong > 9.3.< / strong >  < code > panic!< / code > 还是不< code > panic!< / code > < / a > < / li > < / ul > < / li > < li > < a  href = "ch10-00-generics.html" > < strong > 10.< / strong >  泛型、trait 和生命周期< / a > < / li > < li > < ul  class = "section" > < li > < a  href = "ch10-01-syntax.html" > < strong > 10.1.< / strong >  泛型数据类型< / a > < / li > < li > < a  href = "ch10-02-traits.html" > < strong > 10.2.< / strong >  trait: < / a > < / li > < li > < a  href = "ch10-03-lifetime-syntax.html" > < strong > 10.3.< / strong >  生命周期与引用有效性< / a > < / li > < / ul > < / li > < / ul > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < / div > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < div  id = "page-wrapper"  class = "page-wrapper" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            < div  class = "page" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                < div  id = "menu-bar"  class = "menu-bar" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < div  class = "left-buttons" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                        < i  id = "sidebar-toggle"  class = "fa fa-bars" > < / i > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                        < i  id = "theme-toggle"  class = "fa fa-paint-brush" > < / i > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < / div > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < h1  class = "menu-title" > Rust 程序设计语言 中文版< / h1 > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < div  class = "right-buttons" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                        < i  id = "print-button"  class = "fa fa-print"  title = "Print this book" > < / i > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < / div > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                < / div > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                < div  id = "content"  class = "content" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < h1 > 定义枚举< / h1 > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< blockquote >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > < a  href = "https://github.com/rust-lang/book/blob/master/src/ch06-01-defining-an-enum.md" > ch06-01-defining-an-enum.md< / a >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< br >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								commit 396e2db4f7de2e5e7869b1f8bc905c45c631ad7d< / p > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / blockquote >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								< p > 让我们通过一用代码来表现的场景,来看看为什么这里枚举是有用的而且比结构体更合适。比如我们要处理 IP 地。目前被广泛使用的两个主要 IP 标准: ( ) ( ) < strong > 枚举< / strong > 出所有可能的值,这也正是它名字的由来。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								< p > 任何一个 IP 地址要么是 IPv4 的要么是 IPv6 的而不能两者都是。IP 地址的这个特性使得枚举数据结构非常适合这个场景, < / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								< p > 可以通过在代码中定义一个< code > IpAddrKind< / code > 枚举来表现这个概念并列出可能的 IP 地址类型,< code > V4< / code > 和< code > V6< / code > 。这被称为枚举的< strong > 成员< / strong > ( < em > variants< / em > ) : < / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > enum IpAddrKind { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V4,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V6,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 现在< code > IpAddrKind< / code > 就是一个可以在代码中使用的自定义类型了。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< h3 > 枚举值< / h3 >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 可以像这样创建< code > IpAddrKind< / code > 两个不同成员的实例:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > # enum IpAddrKind { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     V4,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     V6,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let four = IpAddrKind::V4;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let six = IpAddrKind::V6;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								< p > 注意枚举的成员位于其标识符的命名空间中,并使用两个冒号分开。这么设计的益处是现在< code > IpAddrKind::V4< / code > 和< code > IpAddrKind::V6< / code > 是相同类型的:< code > IpAddrKind< / code > 。例如,接着我们可以顶一个函数来获取< code > IpAddrKind< / code > : < / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > # enum IpAddrKind { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     V4,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     V6,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								fn route(ip_type: IpAddrKind) { }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 现在可以使用任意成员来调用这个函数:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > # enum IpAddrKind { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     V4,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     V6,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# fn route(ip_type: IpAddrKind) { }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								route(IpAddrKind::V4);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								route(IpAddrKind::V6);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 使用枚举甚至还有更多优势。进一步考虑一下我们的 IP 地址类型,目前没有一个储存实际 IP 地址< strong > 数据< / strong > 的方法;只知道它是什么< strong > 类型< / strong > 的。考虑到已经在第五章学习过结构体了,你可以想如列表 6-1 那样修改这个问题:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< figure >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > enum IpAddrKind { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V4,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V6,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								struct IpAddr {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    kind: IpAddrKind,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    address: String,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let home = IpAddr {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    kind: IpAddrKind::V4,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    address: String::from(" 127.0.0.1" ),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								};
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let loopback = IpAddr {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    kind: IpAddrKind::V6,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    address: String::from(" ::1" ),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								};
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< figcaption >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > Listing 6-1: Storing the data and < code > IpAddrKind< / code >  variant of an IP address using a 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< code > struct< / code > < / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / figcaption >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / figure >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								< p > 这里我们定义了一个有两个字段的结构体< code > IpAddr< / code > : < code > kind< / code > 字段是< code > IpAddrKind< / code > (之前定义的枚举)类型的而< code > address< / code > 字段是< code > String< / code > 类型的。这里有两个结构体的实例。第一个,< code > home< / code > ,它的< code > kind< / code > 的值是< code > IpAddrKind::V4< / code > 与之相关联的地址数据是< code > 127.0.0.1< / code > 。第二个实例,< code > loopback< / code > , < code > kind< / code > 的值是< code > IpAddrKind< / code > 的另一个成员,< code > V6< / code > ,关联的地址是< code > ::1< / code > 。我们使用了要给结构体来将< code > kind< / code > 和< code > address< / code > 打包在一起,现在枚举成员就与值相关联了。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 我们可以使用一种更简洁的方式来表达相同的概念,仅仅使用枚举并将数据直接放进每一个枚举成员而不是将枚举作为结构体的一部分。< code > IpAddr< / code > 枚举的新定义表明了< code > V4< / code > 和< code > V6< / code > 成员都关联了< code > String< / code > 值:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > enum IpAddr { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V4(String),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V6(String),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let home = IpAddr::V4(String::from(" 127.0.0.1" ));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let loopback = IpAddr::V6(String::from(" ::1" ));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 我们直接将数据附加到枚举的每个成员上,这样就不需要一个额外的结构体了。< / p >  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
									
										 
							
							
								< p > 使用枚举而不是结构体还有另外一个优势: < code > V4< / code > 地址储存为四个< code > u8< / code > 值而< code > V6< / code > 地址仍然表现为一个< code > String< / code > ,这就不能使用结构体了。枚举可以轻易处理的这个情况:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > enum IpAddr { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V4(u8, u8, u8, u8),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V6(String),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let home = IpAddr::V4(127, 0, 0, 1);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let loopback = IpAddr::V6(String::from(" ::1" ));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 这些代码展示了使用枚举来储存两种不同 IP 地址的几种可能的选择。然而,事实证明储存和编码 IP 地址实在是太常见了< a  href = "../std/net/enum.IpAddr.html" > 以致标准库提供了一个可供使用的定义!< / a > <!--  ignore  --> 让我们看看标准库如何定义< code > IpAddr< / code > 的:它正有着跟我们定义和使用的一样的枚举和成员,不过它将成员种的地址数据嵌入到了两个不同形式的结构体中,他们对不同的成员的定义是不同的:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > struct Ipv4Addr { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // details elided
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								struct Ipv6Addr {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    // details elided
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								enum IpAddr {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V4(Ipv4Addr),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    V6(Ipv6Addr),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 这些代码展示了可以将任意类型的数据放入枚举成员中:例如字符串、数字类型或者结构体。甚至可以包含另一个枚举!另外,标准库中的类型通常并不比你可能设想出来的要复杂多少。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 注意虽然标准库中包含一个< code > IpAddr< / code > 的定义,仍然可以创建和使用我们自己的定义而不会有冲突,因为我们并没有将标准库中的定义引入作用域。第七章会讲到如何导入类型。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 来看看列表 6-2 中的另一个枚举的例子:它的成员中内嵌了多种多样的类型:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< figure >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > enum Message { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Quit,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Move { x: i32, y: i32 },
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Write(String),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    ChangeColor(i32, i32, i32),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< figcaption >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > Listing 6-2: A < code > Message< / code >  enum whose variants each store different amounts and 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								types of values< / p > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / figcaption >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / figure >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 这个枚举有四个含有不同类型的成员:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< ul >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< li > < code > Quit< / code > 没有关联任何数据。< / li >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< li > < code > Move< / code > 包含一个匿名结构体< / li >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< li > < code > Write< / code > 包含单独一个< code > String< / code > 。< / li >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< li > < code > ChangeColor< / code > 包含三个< code > i32< / code > 。< / li >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / ul >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 定义一个像列表 6-2 中的枚举类似于定义不同类型的结构体,除了枚举不使用< code > struct< / code > 关键字而且所有成员都被组合在一起位于< code > Message< / code > 下。如下这些结构体可以包含与之前枚举成员中相同的数据:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > struct QuitMessage; // unit struct 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								struct MoveMessage {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    x: i32,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    y: i32,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								struct WriteMessage(String); // tuple struct
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								struct ChangeColorMessage(i32, i32, i32); // tuple struct
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 不过如果我们使用不同的结构体,他们都有不同的类型,将不能轻易的定义一个获取任何这些信息类型的函数,正如可以使用列表 6-2 中定义的< code > Message< / code > 枚举那样因为他们是一个类型的。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 结构体和枚举还有另一个相似点:就像可以使用< code > impl< / code > 来为结构体定义方法那样,也可以在枚举上定义方法。这是一个定义于我们< code > Message< / code > 枚举上的叫做< code > call< / code > 的方法:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > # enum Message { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     Quit,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     Move { x: i32, y: i32 },
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     Write(String),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#     ChangeColor(i32, i32, i32),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								# }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								#
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								impl Message {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    fn call(& self) {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        // method body would be defined here
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let m = Message::Write(String::from(" hello" ));
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								m.call();
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 方法体使用了< code > self< / code > 来获取调用方法的值。这个例子中,创建了一个拥有类型< code > Message::Write(" hello" )< / code > 的变量< code > m< / code > ,而且这就是当< code > m.call()< / code > 运行时< code > call< / code > 方法中的< code > self< / code > 的值。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 让我们看看标准库中的另一个非常常见和实用的枚举:< code > Option< / code > 。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< h3 > < code > Option< / code > 枚举和其相对空值的优势< / h3 >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 在之前的部分,我们看到了< code > IpAddr< / code > 枚举如何利用 Rust 的类型系统编码更多信息而不单单是程序中的数据。这一部分探索一个< code > Option< / code > 的案例分析,它是标准库定义的另一个枚举。< code > Option< / code > 类型应用广泛因为它编码了一个非常普遍的场景,就是一个值可能是某个值或者什么都不是。从类型系统的角度来表达这个概念就意味着编译器需要检查是否处理了所有应该处理的情况,这样就可以避免在其他编程语言中非常常见的 bug。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								< p > 编程语言的设计经常从其包含功能的角度考虑问题, < strong > 空值< / strong > ( < em > Null< / em >  )是一个值它代表没有值。在有空值的语言中,变量总是这两种状态之一:空值和非空值。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								< p > 在“Null References: The Billion Dollar Mistake”中, , < / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< blockquote >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 我称之为我万亿美元的错误。当时,我在在一个面向对象语言设计第一个综合性的面向引用的类型系统。我的目标是通过编译器的自动检查来保证所有引用的应有都应该是绝对安全的。不过我未能抗拒引入一个空引用的诱惑,仅仅是因为它是这么的容易实现。这引发了无数错误、漏洞和系统崩溃,在之后的四十多年中造成了数以万计美元的苦痛和伤害。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / blockquote >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 空值的为题在于当你尝试像一个非空值那样使用一个空值,会出现某种形式的错误。因为空和非空的属性是无处不在的,非常容易出现这类错误。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 然而,空值尝试表达的概念仍然是有意义的:空值是一个因为某种原因目前无效或缺失的值。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
										 
							
							
								< p > 问题不在于实际的概念而在于具体的实现。为此, < code > Option< T> < / code > ,而且它< a  href = "../std/option/enum.Option.html" > 定义于标准库中< / a > <!--  ignore  --> ,如下:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > enum Option< T>  { 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    Some(T),
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    None,
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								}
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > < code > Option< T> < / code > 是如此有用以至于它甚至被包含在了 prelude 之中:不需要显式导入它。另外,它的成员也是如此:可以不需要< code > Option::< / code > 前缀来直接使用< code > Some< / code > 和< code > None< / code > 。即便如此< code > Option< T> < / code > 也仍是常规的枚举,< code > Some(T)< / code > 和< code > None< / code > 仍是< code > Option< T> < / code > 的成员。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > < code > < T> < / code > 语法是一个我们还未讲到的 Rust 功能。它是一个泛型类型参数,第十章会更详细的讲解泛型。目前,所有你需要知道的就是< code > < T> < / code > 意味着< code > Option< / code > 枚举的< code > Some< / code > 成员可以包含任意类型的数据。这里是一些包含数字类型和字符串类型< code > Option< / code > 值的例子:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust" > let some_number = Some(5); 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let some_string = Some(" a string" );
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let absent_number: Option< i32>  = None;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 如果使用< code > None< / code > 而不是< code > Some< / code > ,需要告诉 Rust < code > Option< T> < / code > 是什么类型的,因为编译器只通过< code > None< / code > 值无法推断出< code > Some< / code > 成员的类型。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 当有一个< code > Some< / code > 值时,我们就知道存在一个值,而这个值保存在< code > Some< / code > 中。当有个< code > None< / code > 值时,在某种意义上它跟空值是相同的意义:并没有一个有效的值。那么,< code > Option< T> < / code > 为什么就比空值要好呢?< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 简而言之,因为< code > Option< T> < / code > 和< code > T< / code > (这里< code > T< / code > 可以是任何类型)是不同的类型,编译器不允许像一个被定义的有效的类型那样使用< code > Option< T> < / code > 。例如,这些代码不能编译,因为它尝试将< code > Option< i8> < / code > 与< code > i8< / code > 相比:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code  class = "language-rust,ignore" > let x: i8 = 5; 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let y: Option< i8>  = Some(5);
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								let sum = x + y;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 如果运行这些代码,将得到类似这样的错误信息:< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< pre > < code > error[E0277]: the trait bound `i8: std::ops::Add< std::option::Option< i8> > ` is 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								not satisfied
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								 --> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								7 | let sum = x + y;
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  |           ^^^^^
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								  |
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / code > < / pre >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 哇哦!事实上,错误信息意味着 Rust 不知道该如何将< code > Option< i8> < / code > 与< code > i8< / code > 相加。当在 Rust 中拥有一个像< code > i8< / code > 这样类型的值时,编译器确保它总是有一个有效的值。我们可以自信使用而无需判空。只有当使用< code > Option< i8> < / code > (或者任何用到的类型)是需要担心可能没有一个值,而编译器会确保我们在使用值之前处理为空的情况。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 换句话说,在对< code > Option< T> < / code > 进行< code > T< / code > 的运算之前必须转为< code > T< / code > 。通常这能帮助我们捕获空值最常见的问题之一:假设某值不为空但实际上为空。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 无需担心错过非空值的假设(和处理)让我们对代码更加有信心,为了拥有一个可能为空的值,必须显式的将其放入对应类型的< code > Option< T> < / code > 中。接着,当使用这个值时,必须明确的处理值为空的情况。任何地方一个值不是< code > Option< T> < / code > 类型的话,< strong > 可以< / strong > 安全的假设它的值不为空。这是 Rust 的一个有意为之的设计选择,来限制空值的泛滥和增加 Rust 代码的安全性。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 那么当有一个< code > Option< T> < / code > 的值时,如何从< code > Some< / code > 成员中取出< code > T< / code > 的值来使用它呢?< code > Option< T> < / code > 枚举拥有大量用于各种情况的方法:你可以查看< a  href = "../std/option/enum.Option.html" > 相关代码< / a > <!--  ignore  --> 。熟悉< code > Option< T> < / code > 的方法将对你的 Rust 之旅提供巨大的帮助。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< p > 总的来说,为了使用< code > Option< T> < / code > 值,需要编写处理每个成员的代码。我们想要一些代码只当拥有< code > Some(T)< / code > 值时运行,这些代码允许使用其中的< code > T< / code > 。也希望一些代码当在< code > None< / code > 值时运行,这些代码并没有一个可用的< code > T< / code > 值。< code > match< / code > 表达式就是这么一个处理枚举的控制流结构:它会根据枚举的成员运行不同的代码,这些代码可以使用匹配到的值中的数据。< / p >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                < / div > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                <!--  Mobile navigation buttons  --> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < a  href = "ch06-00-enums.html"  class = "mobile-nav-chapters previous" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                        < i  class = "fa fa-angle-left" > < / i > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < / a > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < a  href = "ch06-02-match.html"  class = "mobile-nav-chapters next" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                        < i  class = "fa fa-angle-right" > < / i > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < / a > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            < / div > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                < a  href = "ch06-00-enums.html"  class = "nav-chapters previous"  title = "You can navigate through the chapters using the arrow keys" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < i  class = "fa fa-angle-left" > < / i > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                < / a > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                < a  href = "ch06-02-match.html"  class = "nav-chapters next"  title = "You can navigate through the chapters using the arrow keys" > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                    < i  class = "fa fa-angle-right" > < / i > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                < / a > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < / div > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        <!--  Local fallback for Font Awesome  --> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            if ($(".fa").css("font-family") !== "FontAwesome") {
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								                $('< link  rel = "stylesheet"  type = "text/css"  href = "_FontAwesome/css/font-awesome.css" > ').prependTo('head');
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								            }
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < / script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        <!--  Livereload script (if served using the cli tool)  --> 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < script  src = "highlight.js" > < / script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								        < script  src = "book.js" > < / script > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								    < / body > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
									
								 
							
							
								< / html >