[譯]使用 Rust 開發一個簡單的 Web 應用,第 2b 部分

LeopPro發表於2018-02-12

使用 Rust 開發一個簡單的 Web 應用,第 2b 部分

目錄

1 系列文章

在這個系列文章中,我記錄下了,我在嘗試使用 Rust 開發一個簡單的 Web 應用過程中獲得的經驗。

到目前為止,我們有:

  1. 制定目標 & “Hello World”級 Web 伺服器
  2. 搞清楚如何寫入檔案

上一篇文章很噁心。這次我們會探索 Rust 的時間、日期格式,重點是用一個合適的格式記錄時間。

2 使用 Chrono

在 crates.io 中搜尋“日期”將得到一個名為 chrono 的包。它熱度很高,更新頻繁,所以這看起來是一個好的候選方案。 從 README 檔案來看,它有著很棒的的日期、時間輸出功能。

第一件事情是在 Cargo.toml 中新增 Chrono 依賴,但在此之前,我們先把舊的 main.rs 移出,騰出空間用於實驗:

$ ls
Cargo.lock Cargo.toml log.txt    src        target
$ cd src/
$ ls
main.rs     web_main.rs
$ git mv main.rs main_file_writing.rs
$ touch main.rs
$ git add main.rs
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   main.rs
        copied:     main.rs -> main_file_writing.rs

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        ../log.txt

$ git commit -m 'move file writing out of the way for working with dates'
[master 4cd2b0e] move file writing out of the way for working with dates
 2 files changed, 16 deletions(-)
 rewrite src/main.rs (100%)
 copy src/{main.rs => main_file_writing.rs} (100%)
複製程式碼

Cargo.toml 中新增 Chrono 依賴:

[package]
name = "simple-log"
version = "0.1.0"
authors = ["Joel McCracken <mccracken.joel@gmail.com>"]

[dependencies]

chrono = "0.2"

[dependencies.nickel]

git = "https://github.com/nickel-org/nickel.rs.git"
複製程式碼

自述檔案接著說:

And put this in your crate root:

    extern crate chrono;
複製程式碼

我不知道這是什麼意思,但我要嘗試把它放到 main.rs 頂部,因為它看起來像是 Rust 程式碼:

extern crate chrono;

fn main() { }
複製程式碼

編譯:

$ cargo run
    Updating registry `https://github.com/rust-lang/crates.io-index`
 Downloading num v0.1.25
 Downloading rand v0.3.8
 Downloading chrono v0.2.14
   Compiling rand v0.3.8
   Compiling num v0.1.25
   Compiling chrono v0.2.14
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
     Running `/Users/joel/Projects/simple-log/target/debug/simple-log`
複製程式碼

好了,它似乎下載了 Chrono,並且編譯成功了、結束了。我想下一步就是嘗試使用它。根據自述檔案第一個例子,我想這樣:

extern crate chrono;
use chrono::*;

fn main() {
    let local: DateTime<Local> = Local::now();
    println!('{}', local);
}
複製程式碼

=>

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
main.rs:6:14: 6:16 error: unterminated character constant: '{
main.rs:6     println!('{}', local);
                       ^~
Could not compile `simple-log`.

To learn more, run the command again with --verbose.
複製程式碼

……?我愣了幾秒後,我意識到它是告訴我,我應該使用雙引號,而不是單引號。這是有道理的,單引號被用於生命週期規範。

從單引號切換到雙引號之後:

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
     Running `/Users/joel/Projects/simple-log/target/debug/simple-log`
2015-06-05 16:54:47.483088 -04:00
複製程式碼

……哇偶,這真簡單。看起來 println! 可以呼叫某種介面以列印各種不同的東西。

這很諷刺。我很輕鬆就構建一個簡單的“Hello World”級 Web 應用並且列印了一個格式良好的時間,但我在寫入檔案上花費了很多時間。我不知道這意味著什麼。儘管 Rust 語言很難用(對我來說),但是我相信 Rust 社群已經做了許多努力使系統包工作良好。

3 將日期時間寫入檔案

我認為,下一步我們應該將這個字串寫入檔案。為此,我想看看上一篇文章的結尾:

$ cat main_file_writing.rs
use std::io::prelude::*;
use std::fs::File;
use std::io;

fn log_something(filename: &'static str, string: &'static [u8; 12]) -> io::Result<()> {
    let mut f = try!(File::create(filename));
    try!(f.write_all(string));
    Ok(())
}

fn main() {
    match log_something("log.txt", b"ITS ALIVE!!!") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

我只是將上面那個例子和這個合併到一起:

extern crate chrono;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use chrono::*;

fn log_something(filename: &'static str, string: &'static [u8; 12]) -> io::Result<()> {
    let mut f = try!(File::create(filename));
    try!(f.write_all(string));
    Ok(())
}

fn main() {
    let local: DateTime<Local> = Local::now();
    println!('{}', local);
    match log_something("log.txt", b"ITS ALIVE!!!") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

編譯:

$ ls
Cargo.lock      Cargo.toml      log.txt         src             target
$ pwd
/Users/joel/Projects/simple-log
$ ls
Cargo.lock      Cargo.toml      log.txt         src             target
$ rm log.txt
$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
     Running `target/debug/simple-log`
2015-06-05 17:08:57.814176 -04:00
File created!
$ cat log.txt
ITS ALIVE!!!$
複製程式碼

它工作了!和語言作鬥爭真有意思,很順利地把兩個東西放在一起。

4 構建時間記錄器

我們離寫一個真正的、完整的、最終系統越來越近。我突然想起,我可以為這個程式碼寫一些測試,但是不急,一會再說。

以下是這個函式應該做的事情:

  1. 給定一個檔名,
  2. 如果它不存在則建立它,然後開啟這個檔案。
  3. 建立一個時間日期字串,
  4. 將這個字串寫入檔案,然後關閉這個檔案。

4.1 對 u8 的誤解

我的第一次嘗試:

extern crate chrono;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use chrono::*;

fn log_time(filename: &'static str) -> io::Result<()> {

    let local: DateTime<Local> = Local::now();
    let time_str = local.format("%Y").to_string();
    let mut f = try!(File::create(filename));
    try!(f.write_all(time_str));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

=>

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
src/main.rs:13:22: 13:30 error: mismatched types:
 expected `&[u8]`,
    found `collections::string::String`
(expected &-ptr,
    found struct `collections::string::String`) [E0308]
src/main.rs:13     try!(f.write_all(time_str));
                                    ^~~~~~~~
<std macros>:1:1: 6:48 note: in expansion of try!
src/main.rs:13:5: 13:33 note: expansion site
error: aborting due to previous error
Could not compile `simple-log`.

To learn more, run the command again with --verbose.
複製程式碼

我知道 Rust 中有很多字串型別1,看起來這裡我需要另一種型別。我不知道怎麼下手,所以我只能搜尋一番。

我記得在 Rust 文件的某一部分中特別提到了字串。查一查,它說,可以使用 & 符號實現從 String&str 的轉換。我感覺這不是我們需要的,因為它應該是 [u8]&str2 之間的型別衝突,讓我們試試:

extern crate chrono;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use chrono::*;

fn log_time(filename: &'static str) -> io::Result<()> {

    let local: DateTime<Local> = Local::now();
    let time_str = local.format("%Y").to_string();
    let mut f = try!(File::create(filename));
    try!(f.write_all(&time_str));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

=>

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
src/main.rs:13:22: 13:31 error: mismatched types:
 expected `&[u8]`,
    found `&collections::string::String`
(expected slice,
    found struct `collections::string::String`) [E0308]
src/main.rs:13     try!(f.write_all(&time_str));
                                    ^~~~~~~~~
<std macros>:1:1: 6:48 note: in expansion of try!
src/main.rs:13:5: 13:34 note: expansion site
error: aborting due to previous error
Could not compile `simple-log`.

To learn more, run the command again with --verbose.
複製程式碼

好吧,顯然,新增 & 符號只能從 String 轉換到 &String。這似乎與 Rust 文件中所說的直相矛盾,但也可能是我不知道發生了什麼事情。

……而且我剛剛讀了字串的章節的末尾。據我所知,這裡沒有任何東西。

我離開了一段時間去忙別的事情(家長裡短,你懂),當我走的時候,我恍然大悟。在此之前,我一直以為 u8UTF-8 的縮寫,但是現在我仔細想想,它肯定是“無符號 8 位整數”的意思。而且我記得我看見過 as_bytes 方法,所以,我們試一下:

extern crate chrono;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use chrono::*;

fn log_time(filename: &'static str) -> io::Result<()> {
    let local: DateTime<Local> = Local::now();
    let bytes = local.format("%Y").to_string().as_bytes();
    let mut f = try!(File::create(filename));
    try!(f.write_all(bytes));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

=>

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
main.rs:10:17: 10:47 error: borrowed value does not live long enough
main.rs:10     let bytes = local.format("%Y").to_string().as_bytes();
                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.rs:10:59: 14:2 note: reference must be valid for the block suffix following statement 1 at 10:
58...
main.rs:10     let bytes = local.format("%Y").to_string().as_bytes();
main.rs:11     let mut f = try!(File::create(filename));
main.rs:12     try!(f.write_all(bytes));
main.rs:13     Ok(())
main.rs:14 }
main.rs:10:5: 10:59 note: ...but borrowed value is only valid for the statement at 10:4
main.rs:10     let bytes = local.format("%Y").to_string().as_bytes();
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.rs:10:5: 10:59 help: consider using a `let` binding to increase its lifetime
main.rs:10     let bytes = local.format("%Y").to_string().as_bytes();
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `simple-log`.

To learn more, run the command again with --verbose.
複製程式碼

好吧,我希望事情有所進展。這個錯誤是否意味著我修正了一些東西,而還有一些其他的錯誤掩蓋了這個問題?我是不是遇到了一個全新的問題?

奇怪的是錯誤資訊集中體現在同一行上。我並不是很明白,但我覺得它是想告訴我,我需要新增一個賦值語句在方法中。我們試一下:

fn log_time(filename: &'static str) -> io::Result<()> {
    let local: DateTime<Local> = Local::now();
    let formatted = local.format("%Y").to_string();
    let bytes = formatted.as_bytes();
    let mut f = try!(File::create(filename));
    try!(f.write_all(bytes));
    Ok(())
}
複製程式碼

=>

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
     Running `target/debug/simple-log`
File created!
$ cat log.txt
2015$
複製程式碼

太棒了!我們想要的都在這了。在我繼續之前,我想吐槽一下,我有一點失望。沒有我的提示,Rust 也應該可以通過上下文推斷正確的行為。

測試指令碼:

$ ls
Cargo.lock      Cargo.toml      log.txt         src             target
$ rm log.txt
$ cargo run
     Running `target/debug/simple-log`
File created!
$ cat log.txt
2015$ cargo run
     Running `target/debug/simple-log`
File created!
$ cat log.txt
2015$
複製程式碼

4.2 查缺補漏

一些問題:

  1. 沒有另起一行,這忍不了。
  2. 格式需要一些處理。
  3. 新的日期會覆蓋舊的。

Let's verify #3 by fixing the format. If the time changes between runs, then we will know that's what is happening.

DateTime 中的 format 方法使用標準 strftime 格式公約。理想情況下,我希望時間看起來像是這樣的:

Sat, Jun 6 2015 05:32:00 PM
Sun, Jun 7 2015 08:35:00 AM
複製程式碼

……等等。這可讀性應該是足夠的,供我使用。查閱文件後,我想出了這個:

extern crate chrono;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use chrono::*;

fn log_time(filename: &'static str) -> io::Result<()> {
    let local: DateTime<Local> = Local::now();
    let formatted = local.format("%a, %b %d %Y %I:%M:%S %p\n").to_string();
    let bytes = formatted.as_bytes();
    let mut f = try!(File::create(filename));
    try!(f.write_all(bytes));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

測試:

$ rm log.txt
$ cargo run
     Running `target/debug/simple-log`
File created!
$ cat log.txt
Sun, Jun 07 2015 06:37:21 PM
$ sleep 5; cargo run
     Running `target/debug/simple-log`
File created!
$ cat log.txt
Sun, Jun 07 2015 06:37:41 PM
複製程式碼

顯然,程式覆蓋我想要的日誌項。我記得 File::create 的文件中指出了這裡發生的事。所以,為了正確處理檔案我需要再次查閱文件。

我進行了一些搜尋,基本上找到答案都是無關緊要的。隨後,我找到了 std::path::Path 的文件,其中有一個 exists 模式。

此時,我的程式中的型別轉換變得越來越難以管理。我感到緊張,所以繼續之前,我要提交一次。

我想把對時間實體字串的處理邏輯從 log_time 函式中抽取出來,因為時間的建立與格式化顯然與檔案操作程式碼不同。所以,我做了如下嘗試:

extern crate chrono;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use chrono::*;

fn log_time_entry() -> String {
    let local: DateTime<Local> = Local::now();
    let formatted = local.format("%a, %b %d %Y %I:%M:%S %p\n").to_string();
    formatted
}

fn log_time(filename: &'static str) -> io::Result<()> {
    let bytes = log_time_entry().as_bytes();
    let mut f = try!(File::create(filename));
    try!(f.write_all(bytes));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

=>

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
src/main.rs:16:17: 16:33 error: borrowed value does not live long enough
src/main.rs:16     let bytes = log_time_entry().as_bytes();
                               ^~~~~~~~~~~~~~~~
src/main.rs:16:45: 20:2 note: reference must be valid for the block suffix following statement 0 at
 16:44...
src/main.rs:16     let bytes = log_time_entry().as_bytes();
src/main.rs:17     let mut f = try!(File::create(filename));
src/main.rs:18     try!(f.write_all(bytes));
src/main.rs:19     Ok(())
src/main.rs:20 }
src/main.rs:16:5: 16:45 note: ...but borrowed value is only valid for the statement at 16:4
src/main.rs:16     let bytes = log_time_entry().as_bytes();
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:16:5: 16:45 help: consider using a `let` binding to increase its lifetime
src/main.rs:16     let bytes = log_time_entry().as_bytes();
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `simple-log`.

To learn more, run the command again with --verbose.
複製程式碼

好吧,這看起來就像我以前遇到的問題。是不是假借或持有要求函式擁有明確的資源引用?這似乎有一點奇怪。我再次嘗試修復它:

extern crate chrono;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use chrono::*;

fn formatted_time_entry() -> String {
    let local: DateTime<Local> = Local::now();
    let formatted = local.format("%a, %b %d %Y %I:%M:%S %p\n").to_string();
    formatted
}

fn log_time(filename: &'static str) -> io::Result<()> {
    let entry = formatted_time_entry();
    let bytes = entry.as_bytes();

    let mut f = try!(File::create(filename));
    try!(f.write_all(bytes));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

=>

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
     Running `target/debug/simple-log`
File created!
複製程式碼

所以,看起來新增一個明確的引用解決了問題。不管怎樣,這個規則還蠻簡單。

下面,我要將檔案操作程式碼抽取至它自己的函式:

extern crate chrono;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use chrono::*;

fn formatted_time_entry() -> String {
    let local: DateTime<Local> = Local::now();
    let formatted = local.format("%a, %b %d %Y %I:%M:%S %p\n").to_string();
    formatted
}

fn record_entry_in_log(filename: &str, bytes: &[u8]) -> io::Result<()> {
    let mut f = try!(File::create(filename));
    try!(f.write_all(bytes));
    Ok(())
}

fn log_time(filename: &'static str) -> io::Result<()> {
    let entry = formatted_time_entry();
    let bytes = entry.as_bytes();

    try!(record_entry_in_log(filename, &bytes));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

它正常工作。我犯了一些一開始的錯誤,但它們很快被糾正了。這裡已經是修改後的程式碼。

查閱文件中的 std::fs::File,我注意到文件對 std::fs::OpenOptions 的介紹,這正是我一直在尋找的。這肯定比使用 std::path 更好。

我的第一次嘗試:

extern crate chrono;

use std::io::prelude::*;
use std::fs::{File,OpenOptions};
use std::io;
use chrono::{DateTime,Local};

fn formatted_time_entry() -> String {
    let local: DateTime<Local> = Local::now();
    let formatted = local.format("%a, %b %d %Y %I:%M:%S %p\n").to_string();
    formatted
}

fn record_entry_in_log(filename: &str, bytes: &[u8]) -> io::Result<()> {
    let mut file = try!(OpenOptions::new().
                        append(true).
                        create(true).
                        open(filename));
    try!(file.write_all(bytes));
    Ok(())
}

fn log_time(filename: &'static str) -> io::Result<()> {
    let entry = formatted_time_entry();
    let bytes = entry.as_bytes();

    try!(record_entry_in_log(filename, &bytes));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(..) => println!("Error: could not create file.")
    }
}
複製程式碼

=>

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
src/main.rs:4:15: 4:19 warning: unused import, #[warn(unused_imports)] on by default
src/main.rs:4 use std::fs::{File,OpenOptions};
                            ^~~~
     Running `target/debug/simple-log`
Error: could not create file.
複製程式碼

有趣。其實它成功建立檔案了。哦,我注意錯誤提示是我硬編碼到 main 的資訊。我認為這樣它將工作:

extern crate chrono;

use std::io::prelude::*;
use std::fs::{File,OpenOptions};
use std::io;
use chrono::{DateTime,Local};

fn formatted_time_entry() -> String {
    let local: DateTime<Local> = Local::now();
    let formatted = local.format("%a, %b %d %Y %I:%M:%S %p\n").to_string();
    formatted
}

fn record_entry_in_log(filename: &str, bytes: &[u8]) -> io::Result<()> {
    let mut file = try!(OpenOptions::new().
                        append(true).
                        create(true).
                        open(filename));
    try!(file.write_all(bytes));
    Ok(())
}

fn log_time(filename: &'static str) -> io::Result<()> {
    let entry = formatted_time_entry();
    let bytes = entry.as_bytes();

    try!(record_entry_in_log(filename, &bytes));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(e) => println!("Error: {}", e)
    }
}
複製程式碼

=>

$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
src/main.rs:4:15: 4:19 warning: unused import, #[warn(unused_imports)] on by default
src/main.rs:4 use std::fs::{File,OpenOptions};
                            ^~~~
     Running `target/debug/simple-log`
Error: Bad file descriptor (os error 9)
複製程式碼

奇怪。搜尋“非法的檔案描述”錯誤資訊似乎表明,被使用的檔案描述已經被關閉了。如果我註釋掉 file.write_all 呼叫,將會發生什麼呢?

$ rm log.txt
$ cargo run
   Compiling simple-log v0.1.0 (file:///Users/joel/Projects/simple-log)
src/main.rs:3:5: 3:25 warning: unused import, #[warn(unused_imports)] on by default
src/main.rs:3 use std::io::prelude::*;
                  ^~~~~~~~~~~~~~~~~~~~
src/main.rs:4:15: 4:19 warning: unused import, #[warn(unused_imports)] on by default
src/main.rs:4 use std::fs::{File,OpenOptions};
                            ^~~~
src/main.rs:15:40: 15:45 warning: unused variable: `bytes`, #[warn(unused_variables)] on by default
src/main.rs:15 fn record_entry_in_log(filename: &str, bytes: &[u8]) -> io::Result<()> {
                                                      ^~~~~
src/main.rs:16:9: 16:17 warning: unused variable: `file`, #[warn(unused_variables)] on by default
src/main.rs:16     let mut file = try!(OpenOptions::new().
                       ^~~~~~~~
src/main.rs:16:9: 16:17 warning: variable does not need to be mutable, #[warn(unused_mut)] on by de
fault
src/main.rs:16     let mut file = try!(OpenOptions::new().
                       ^~~~~~~~
     Running `target/debug/simple-log`
File created!
$ ls
Cargo.lock      Cargo.toml      log.txt         src             target
複製程式碼

不出所料,有一堆未使用的警告資訊,但是無他,檔案的確被建立了。

這似乎有點傻,但我嘗試向函式呼叫鏈中新增 .write(true) 後,它工作了。語義上 .append(true) 就意味著 .write(true),但我想規定上不是這樣的。

搞定了這個,它工作了!最終版本:

extern crate chrono;

use std::io::prelude::*;
use std::fs::{File,OpenOptions};
use std::io;
use chrono::{DateTime,Local};

fn formatted_time_entry() -> String {
    let local: DateTime<Local> = Local::now();
    let formatted = local.format("%a, %b %d %Y %I:%M:%S %p\n").to_string();
    formatted
}

fn record_entry_in_log(filename: &str, bytes: &[u8]) -> io::Result<()> {
    let mut file = try!(OpenOptions::new().
                        append(true).
                        write(true).
                        create(true).
                        open(filename));
    try!(file.write_all(bytes));
    Ok(())
}

fn log_time(filename: &'static str) -> io::Result<()> {
    let entry = formatted_time_entry();
    let bytes = entry.as_bytes();

    try!(record_entry_in_log(filename, &bytes));
    Ok(())
}

fn main() {
    match log_time("log.txt") {
        Ok(..) => println!("File created!"),
        Err(e) => println!("Error: {}", e)
    }
}
複製程式碼

=>

$ ls
Cargo.lock      Cargo.toml      src             target
$ cargo run
     Running `target/debug/simple-log`
File created!
$ cargo run
     Running `target/debug/simple-log`
File created!
$ cat log.txt
Sun, Jun 07 2015 10:40:01 PM
Sun, Jun 07 2015 10:40:05 PM
複製程式碼

5 結論 & 後續步驟

Rust 對我來說越來越容易了。我現在有一些有效的、單功能的程式碼可以使用,我對下一部分程式的開發感到相當有信心。

當我首次規劃這個系列的時候,我計劃下一個任務是整合日誌程式碼和 nickel.rs 程式碼,但是現在,我認為這是非常簡單的。我猜測,下一個有挑戰的部分將是處理選項解析

系列文章:使用 Rust 開發一個簡單的 Web 應用

腳註:

1 有很多種類的字串是非常合理的事情。字串是一個複雜的實體,很難得到正確的表達。不幸的是,乍一看字串非常簡單,這種事情似乎沒必要複雜。

2 我也不知道我在說什麼。這些就是現在所能企及的。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章