Rust的文档建议在可能的情况下使用& str,并且只有在不可能的情况下才使用它,使用String。总是这样吗?例如,我正在为Web服务的REST API构建客户端,并且我有一个实体:
struct User {
id: &str // or String?
name: &str // or String?
//......
}
一般而言,在这种特殊情况下使用&str
或String
会更好吗?
答案 0 :(得分:9)
在Rust中,与决定是否使用引用有关的一切都源于所有权和借用及其应用的基本概念。在设计数据结构时,没有干净的规则:它完全取决于您的确切用例。
例如,如果您的数据结构旨在提供某些其他数据结构的视图(如迭代器那样),则使用引用和切片作为其字段是有意义的。另一方面,如果您的结构是DTO,那么让它拥有所有数据更为自然。
我认为在可能的情况下使用&str
的建议更适用于函数定义,在这种情况下它确实很自然:如果您使函数接受&str
而不是{{1} },如果他们有String
或String
,他们的来电者就可以轻松使用它们而且不收取任何费用;另一方面,如果您的函数接受&str
s,那么如果他们的调用者有String
,他们将被迫分配新的&str
,即使他们有String
但是不想放弃所有权,他们仍然需要克隆它。
但当然也有例外:有时您确实希望在函数内部转移所有权。某些数据结构和特征(如String
或Option
)提供了将所拥有的变体转换为借用变体(Reader
和Option::as_ref()
)的功能,这些变体有时很有用。还有一种Cow
类型,它对所有权进行“抽象”,允许您传递借用的值,必要时将对其进行克隆。有时会有像BytesContainer
这样的特征,它可以抽象各种类型,拥有和借用,并允许调用者传递不同类型的值。
我想再次强调的是,没有固定的规则,它完全取决于你正在进行的具体任务。在构建数据结构时,应该使用常识和所有权/借用概念。
在您的特定情况下,是否使用Reader::by_ref()
或String
取决于您将对&str
对象实际执行的操作 - 遗憾的是,“REST API客户端”过于模糊。这取决于您的架构。如果这些对象仅使用 来执行HTTP请求,但数据实际存储在其他某些源中,那么您可能希望使用User
。另一方面,如果在整个程序中使用&str
个对象,那么使用User
s使它们拥有数据是有意义的。