也许解释根本区别的最简单方法是,枚举包含“变体”,一次只能拥有一个变体,而结构体包含一个或多个字段,您必须拥有所有这些字段。
因此,您可以使用 anenum
来建模诸如错误代码之类的东西,其中一次只能有一个:
enum ErrorCode {
NoDataReceived,
CorruptedData,
BadResponse,
}
Run Code Online (Sandbox Code Playgroud)
如果需要,枚举变体可以包含值。例如,我们可以添加一个案例,ErrorCode
如下所示:
enum ErrorCode {
NoDataReceived,
CorruptedData,
BadResponse,
BadHTTPCode(u16),
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下, 的实例ErrorCode::BadHTTPCode
始终包含u16
.
这使得每个单独的变体的行为有点像元组结构或单元结构:
// Unit structs have no fields
struct UnitStruct;
// Tuple structs contain anonymous values.
struct TupleStruct(u16, &'static str);
Run Code Online (Sandbox Code Playgroud)
但是,将它们编写为枚举变体的优点是, 的每种情况都ErrorCode
可以存储在 type 的值中ErrorCode
,如下所示(这对于不相关的结构是不可能的)。
fn handle_error(error: ErrorCode) {
match error {
ErrorCode::NoDataReceived => println!("No data received."),
ErrorCode::CorruptedData => println!("Data corrupted."),
ErrorCode::BadResponse => println!("Bad response received from server."),
ErrorCode::BadHTTPCode(code) => println!("Bad HTTP code received: {}", code)
};
}
fn main() {
handle_error(ErrorCode::NoDataReceived); // prints "No data received."
handle_error(ErrorCode::BadHTTPCode(404)); // prints "Bad HTTP code received: 404"
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以match
在枚举上确定您获得的变体,并根据它是哪一个变体执行不同的操作。
相比之下,我上面没有提到的第三种结构是最常用的 - 这是每个人在简单地说“结构”时所指的结构类型。
struct Response {
data: Option<Data>,
response: HTTPResponse,
error: String,
}
fn main() {
let response = Response {
data: Option::None,
response: HTTPResponse::BadRequest,
error: "Bad request".to_owned()
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,为了创建Response
,必须为其所有字段指定值。
response
另外, 的值的创建方式(即HTTPResponse::Something
)意味着它HTTPResponse
是一个枚举。它可能看起来像这样:
enum HTTPResponse {
Ok, // 200
BadRequest, // 400
NotFound, // 404
}
Run Code Online (Sandbox Code Playgroud)