< 返回版块

GuangGuo 发表于 2023-01-28 20:40

Tags:format!()

fn main() {
    let _ = format!("Hello, {}!", "world");
    let tmp = "Hello, {}!";
    let _ = format!(tmp, "world");  // 报错
}

标准库中有注明, From these, you can see that the first argument is a format string. It is required by the compiler for this to be a string literal; it cannot be a variable passed in (in order to perform validity checking). The compiler will then parse the format string and determine if the list of arguments provided is suitable to pass to this format string.

但是, 在其他语言中, 将报错信息存储在一起, 取用的时候再进行格式化应该是一个很常见的做法. 类似于:

use std::collections::HashMap;

fn main() {
    let errcode = HashMap::from([
        ("Err0".to_string(), "Err0: {}".to_string()),
        ("Err1".to_string(), "Err1: {} {}".to_string()),
    ]);

    let err = "Err1";
    if let Some(val) = errcode.get(err) {
        let _ = format!(val, "foo", "bar");  // 报错
    }
}

所以想请问一下, 面对这样的需求, 有什么好的方法吗? 或者有更适合 Rust 的范式?

评论区

写评论
作者 GuangGuo 2023-01-31 13:29

感谢感谢!

--
👇
johnmave126: 用enum然后定义Display是比较Rust的做法吧,建议直接使用thiserror。然后可以给错误实现一个TryFrom<u32>或者FromStr来达成你现在的从一个错误码实例化错误的事情。

johnmave126 2023-01-29 09:30

enum然后定义Display是比较Rust的做法吧,建议直接使用thiserror。然后可以给错误实现一个TryFrom<u32>或者FromStr来达成你现在的从一个错误码实例化错误的事情。

作者 GuangGuo 2023-01-28 23:17

多谢多谢! 拨云见日, 豁然开朗!

--
👇
苦瓜小仔: 首先,见同一个问题:https://stackoverflow.com/questions/32572486/how-can-i-use-a-dynamic-format-string-with-the-format-macro

format! 第一个参数必须为字符串,而不支持为变量,原因在于标准库想要编译时检查。

所以,几种方案:

  1. 字符串替换(正则、非正则)
  2. 模版或类似的东西(很多库可选了) 例子
  3. 利用 Rust 类型系统 playground
苦瓜小仔 2023-01-28 21:43

首先,见同一个问题:https://stackoverflow.com/questions/32572486/how-can-i-use-a-dynamic-format-string-with-the-format-macro

format! 第一个参数必须为字符串,而不支持为变量,原因在于标准库想要编译时检查。

所以,几种方案:

  1. 字符串替换(正则、非正则)
  2. 模版或类似的东西(很多库可选了) 例子
  3. 利用 Rust 类型系统 playground
作者 GuangGuo 2023-01-28 21:32

多谢! 我刚才想了一个返回闭包的版本, 但是涉及到多参数和参数的类型, 基本无法实现.

fn foo(s: &str) -> impl Fn() -> String {
    match s {
        "a" => || format!("no parameters"),
        "b" => |n| format!("one parameters {}", n),
        "c" => |n1, n2| format!("two parameters {} {:<20}", n1, n2),
        "d" => |n1, n2, n3| format!("three parameters {} {:<20} {:<30}", n1, n2, n3),
        _ => || format!("invalid parameters"),
    }
}

.replace() 确实是个没办法的好办法.

--
👇
Mike Tang: 是的,所以我暂时是用的这种方式:

const AAA: &str = "FooBar:{#}";

let a_new_string = AAA.replace("#", foobar);


Mike Tang 2023-01-28 21:03

是的,所以我暂时是用的这种方式:

const AAA: &str = "FooBar:{#}";

let a_new_string = AAA.replace("#", foobar);


1 共 6 条评论, 1 页