字符串连接错误:期望字面量

5

所以我有这样一个问题:

struct User {
    reference: String,
    email: String,
    firstname: String,
    lastname: String
}

fn main() {

    let user = User {
        reference: "ref".to_string(),
        email: "em@ail.com".to_string(),
        firstname: "John".to_string(),
        lastname: "Doe".to_string()
    };

    concat!(&user.firstname.as_string(), " ", &user.lastname.as_string());

}

这里返回了一个错误:

error: expected a literal
concat!(&user.firstname.as_string(), " ", &user.lastname.as_string());
        ^~~~~~~~~~~~~~~~~~~~~~~~~~

但是我认为.as_string()已经使其成为文字了,不是吗?我还发现到处都有as_slice()as_str()的引用,这很令人困惑。到底哪一个是正确的?

更新好的,我希望不必在这里粘贴整个内容,但我似乎必须这样做:

extern crate postgres;

use postgres::{Connection, SslMode};

struct User {
    reference: String,
    email: String,
    firstname: String,
    lastname: String
}

fn main() {

    let conn = Connection::connect("postgres://postgres:postgres@localhost/mydb", &SslMode::None).unwrap();

    let user = User {
        reference: "ref".to_string(),
        email: "em@ail.com".to_string(),
        firstname: "John".to_string(),
        lastname: "Doe".to_string()
    };
    let query = "INSERT INTO foo (user_id, name) VALUES ((SELECT id FROM user WHERE email = $1), $2)";
    conn.execute(query, &[&user.email, concat!(&user.firstname.as_slice(), " ", &user.lastname.as_slice())]).unwrap();

}

你在这里究竟想要实现什么? - Daniel Fath
@DanielFath 更新了上下文代码。 - Caballero
2个回答

12
这里存在误解。 concat!是一个宏,是一种“代码生成”机制;因此,在编译的早期阶段(在类型解析/所有权检查等之前)会进行展开。
字面量是以原样写入代码中的值:true1"hello";一个表达式的结果不能够是一个字面量(根据定义)。尽管得到的类型可能看起来相似(甚至完全相同),但这里类型无关紧要。
所以,你真正想要什么?我猜你只是想连接字符串。对于String,你可以使用+:
let fullname = user.firstname + " " + user.lastname;
conn.execute(query, &[&user.email, &fullname]).unwrap();

如果您需要一些更加复杂的格式,可以使用 format! 宏(不需要文字字面量),示例如下:

let fullname = format!("{} {}", user.firstname, user.lastname);

3
Rust的concat!期望字面量,例如符号字面量(如true32 'c'"string"),因为它在编译阶段的最早部分工作。在这段时间内,类型的运行时值尚未解析。
根据您的Postgresql示例,最好的做法似乎是创建一个返回全名或所需内容的函数:
struct User {
    ... //same
}

impl User {

   fn get_fullname(&self) -> String
   {
       let mut fullname = String::new();
       fullname.push_str(&self.firstname);
       fullname.push_str(" ");
       fullname.push_str(&self.lastname);
       fullname
   }
}

fn main() {

    let user = User {
        reference: "ref".to_string(),
        email: "em@ail.com".to_string(),
        firstname: "John".to_string(),
        lastname: "Doe".to_string()
    };
    let x = &[&user.email, &user.get_fullname()];
    conn.execute(query, &[x]);

我提议这样做,因为似乎在结构体中经常需要使用获取完整姓名的功能。但如果不需要,你可以像Matthiueu M.建议的那样格式化值,然后将它们串联起来,假设这只是一次性的事情。

(Playground)


2
澄清一下:concat!完全在编译时完成其工作;它根本无法连接运行时值。你想要的是像format!("{} {}", first, second)这样的东西。 - DK.
1
@DK。谢谢,这正是我所需要的。 - Caballero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接