简体   繁体   English

在 rust 中实例化错误时出现问题

[英]Problems while instantiating an error in rust

I have a struct that contains the return code and the data retrieved from a postgres query.我有一个结构,其中包含返回代码和从 postgres 查询中检索到的数据。 I have a new() function that initializes the struct:我有一个初始化结构的 new() function:

impl <T> Response <T>
     {
     pub fn new() -> Response <T>
             {
             return Response
                 {
                 rc : RetCode::Ok,
 ------>         pg_err : Error::new(),
                 desc : "".to_string(),
                 data : Vec::new(), 
                 id : 0,
                }

but the postgres::Error::new() is private.但是 postgres::Error::new() 是私有的。 Is there a way to create a new error ( i don't mind the type or content), just for placeholder for actual, future error?有没有办法创建一个新的错误(我不介意类型或内容),只是为了实际的未来错误的占位符? i don't need Null, just a fake error, because in RetCode i have ok, no-data-retrieved, postgre error, so i need to check the error just when retcode is pg_error.我不需要 Null,只是一个假错误,因为在 RetCode 中我有 ok,no-data-retrived,postgre 错误,所以我需要在 retcode 为 pg_error 时检查错误。

As mentioned in the comments, there is no public way to create a postgres::Error .正如评论中提到的,没有公开的方法来创建postgres::Error You can only get one from some other postgres operation that fails.您只能从其他一些失败的 postgres 操作中获得一个。 You can use the linked answer and use an Option to create the pg_err with None before an error occurs, and filling it with Some(...) when it does.您可以使用链接的答案并使用Option在发生错误之前使用None创建pg_err ,并在错误发生时使用Some(...)填充它。

However, that is not the way you should solve this particular problem.但是,这不是您应该解决此特定问题的方式。 You have a single type that is designed to express multiple different forms of responses: "ok", "no-data", and "error" as you've mentioned in the comments.您有一个单一类型,旨在表达多个不同的 forms 响应:“ok”、“no-data”和“error”,正如您在评论中提到的那样。 So it sounds like you have RetCode designed as such:所以听起来你的RetCode是这样设计的:

enum RetCode { Ok, NoData, Error }

But Rust enum s are much more powerful than in other languages, they can hold data exclusive to a specific variant.但是 Rust enum比其他语言强大得多,它们可以保存特定变体专有的数据。 There is a philosophy to "make invalid states unrepresentable".有一种哲学是“使无效状态无法代表”。 In other words, why have a pg_err if no error occurred?换句话说,如果没有发生错误,为什么会有pg_err呢? Why have a data field if the status is NoData ?如果状态为NoData ,为什么还要有一个data字段?

You can restructure your objects like so:您可以像这样重组对象:

enum ResponseKind<T> {
    Ok { data: Vec<T> },
    NoData,
    Error { pg_err: postgres::Error },
}

struct Response<T> {
    id: i32,
    desc: String,
    kind: ResponseKind<T>,
}

That way you don't have to worry about creating some dummy error type.这样您就不必担心创建一些虚拟错误类型。

You should heed the other comments;您应该注意其他评论; don't fall into the trap of simply creating a dummy constructor just for the sake of it.不要陷入仅仅为了它而简单地创建一个虚拟构造函数的陷阱。 And new() is just a convention which shouldn't be followed if there's no obvious default state for your type. new()只是一个约定,如果您的类型没有明显的默认 state,则不应遵循该约定。 You should have constructor functions with parameters that provide valid data to construct it with.您应该具有带有参数的构造函数,这些参数提供有效数据来构造它。 Like:喜欢:

impl<T> Response<T> {
    pub fn ok(id: i32, desc: String, data: Vec<T>) -> Response<T> {
        // or maybe id and desc are generated or dependent on
        // kind and don't need to be parameters?
        Response {
            id,
            desc,
            kind: ResponseKind::Ok { data },
        }
    }

    pub fn no_data(id: i32, desc: String) -> Response<T> { ... }
    pub fn error(id: i32, desc: String, error: Error) -> Response<T> { ... }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM