println 的高階用法

println! (及其兄弟, print! )提供了一種方便的機制,用於生成和列印包含動態資料的文字,類似於許多其他語言中的 printf 系列函式。它的第一個引數是一個格式字串,它指示其他引數應該如何作為文字列印。格式字串可能包含佔位符(包含在 {} 中)以指定應發生替換:

// No substitution -- the simplest kind of format string
println!("Hello World");
// Output: Hello World

// The first {} is substituted with a textual representation of
// the first argument following the format string. The second {}
// is substituted with the second argument, and so on.
println!("{} {} {}", "Hello", true, 42);
// Output: Hello true 42

此時,你可能會問:println! 如何知道將布林值 true 列印為字串 true{} 實際上是對格式化程式的指令,應該使用 Display 特性將值轉換為文字。這個特性是針對大多數原始的 Rust 型別(字串,數字,布林值等)實現的,並且用於面向使用者的輸出。因此,數字 42 將以十進位制形式列印為 42,而不是二進位制列印,這是它在內部儲存的方式。

那麼,我們如何列印實現 Display 的型別,例如 Slices([i32]),vectors(Vec<i32>)或 options(Option<&str>)?沒有明確的面向使用者的文字表示(即你可以輕易插入一個句子)。為了便於列印這些值,Rust 還具有 Debug 特性,以及相應的 {:?} 佔位符。從文件中可以看出:“Debug 應該在面向程式設計師的除錯環境中格式化輸出。” 我們來看一些例子:

println!("{:?}", vec!["a", "b", "c"]);
// Output: ["a", "b", "c"]

println!("{:?}", Some("fantastic"));
// Output: Some("fantastic")

println!("{:?}", "Hello");
// Output: "Hello"
// Notice the quotation marks around "Hello" that indicate
// that a string was printed.

Debug 還有一個內建的漂亮印表機制,你可以在冒號後使用 # 修飾符啟用:

println!("{:#?}", vec![Some("Hello"), None, Some("World")]);
// Output: [
//    Some(
//        "Hello"
//    ),
//    None,
//    Some(
//        "World"
//    )
// ]

格式字串允許你表達相當複雜的替換

// You can specify the position of arguments using numerical indexes.
println!("{1} {0}", "World", "Hello");
// Output: Hello World

// You can use named arguments with format
println!("{greeting} {who}!", greeting="Hello", who="World");
// Output: Hello World

// You can mix Debug and Display prints:
println!("{greeting} {1:?}, {0}", "and welcome", Some(42), greeting="Hello");
// Output: Hello Some(42), and welcome

println! 和朋友也會警告你,如果你試圖做一些不起作用的事情,而不是在執行時崩潰:

// This does not compile, since we don't use the second argument.
println!("{}", "Hello World", "ignored");

// This does not compile, since we don't give the second argument.
println!("{} {}", "Hello");

// This does not compile, since Option type does not implement Display
println!("{}", Some(42));

在它的核心,Rust 列印巨集只是圍繞 format! 巨集的包裝器,它允許通過將不同資料值的文字表示拼接在一起來構造字串。因此,對於上面的所有示例,你可以用 println! 替換 format! 來儲存格式化的字串而不是列印它:

let x: String = format!("{} {}", "Hello", 42);
assert_eq!(x, "Hello 42");