1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Rust 項(xiàng)目實(shí)戰(zhàn):從頭構(gòu)建一個(gè)筆記命令行程序(1)

        共 6446字,需瀏覽 13分鐘

         ·

        2022-02-10 22:28

        學(xué)習(xí)了 Rust 的語法后,我對這門語言感覺良好。于是計(jì)劃實(shí)戰(zhàn)一下。這篇文章是系列文章中的第一篇,該系列將介紹如何使用 Rust 構(gòu)建筆記應(yīng)用程序。

        最終目標(biāo)是為讀者提供足夠的知識來構(gòu)建自己的類似于 engram[1] 的筆記應(yīng)用程序。

        本系列內(nèi)容希望讀者具備一些編程知識,但可能是 Rust 新手。該系列的每個(gè)部分都將產(chǎn)生一個(gè)功能性和有用的應(yīng)用程序,將在以后的文章中構(gòu)建。

        我強(qiáng)烈建議手動(dòng)敲入你看到的代碼,而不僅僅是復(fù)制和粘貼。這是獲得更好理解的最有效方法之一。

        01 入門

        從 Rust 官網(wǎng)找到入門頁面:https://www.rust-lang.org/learn/get-started,根據(jù)介紹安裝 Rust。

        安裝 Rust

        curl?--proto?'=https'?--tlsv1.2?-sSf?https://sh.rustup.rs?|?sh

        創(chuàng)建新的 Rust 項(xiàng)目

        cargo?new?notes

        cargo 是 Rust 包管理器[2]。它支持多種命令,本文將介紹其中的幾個(gè)。cargo new 在當(dāng)前目錄中創(chuàng)建一個(gè)名為 notes(或你指定的任何其他內(nèi)容)的新項(xiàng)目(和文件夾)。

        src/main.rs 包含一個(gè)簡單的“Hello World”應(yīng)用程序。

        Cargo.toml 被稱為清單。請參閱 The Cargo Book[3] 以深入了解此處支持的內(nèi)容。我們只需要在這里做一個(gè)小的調(diào)整來添加一個(gè)依賴項(xiàng),所以不要太擔(dān)心現(xiàn)在不理解全部內(nèi)容。

        默認(rèn)情況下,.gitignore 可以方便地從 git 中忽略目標(biāo)文件夾。

        運(yùn)行 hello world 應(yīng)用程序

        cargo?run

        cargo run[4] 命令構(gòu)建并運(yùn)行當(dāng)前的包。在本教程進(jìn)行更改后,你將使用它來運(yùn)行和測試這些更改。運(yùn)行一次后,你會(huì)看到更多的文件和文件夾出現(xiàn)。

        Cargo.lock 這是一個(gè)自動(dòng)生成的文件,它準(zhǔn)確指定了正在使用的庫的版本。有關(guān) Cargo.toml 與 Cargo.lock 的更多詳細(xì)信息,請參閱 Cargo Book[5]。

        target 這個(gè)文件夾是存儲(chǔ)所有構(gòu)建文件的地方。你幾乎可以忽略這一點(diǎn),因?yàn)?cargo 工具會(huì)根據(jù)需要處理它。

        在 VS Code 中打開的默認(rèn) Rust 工作區(qū)

        02 準(zhǔn)備數(shù)據(jù)模型

        先從數(shù)據(jù)庫開始。

        創(chuàng)建一個(gè) sqlite3 數(shù)據(jù)庫

        數(shù)據(jù)庫是幾乎所有應(yīng)用程序的核心。大多數(shù)新功能需要存儲(chǔ)一些新數(shù)據(jù)或以某種方式檢索現(xiàn)有信息。由于這些原因,這通常是你在構(gòu)建新事物時(shí)應(yīng)該考慮的第一件事。特別是,我試圖構(gòu)建的 “schema” 是什么。

        就本教程而言,我們的 schema 非常簡單。我們想要一個(gè)帶有 id 列和 body 列的 notes 表。id 存儲(chǔ)特定筆記的唯一標(biāo)識符。這是大多數(shù)數(shù)據(jù)庫的必填字段,因?yàn)樗试S你直接引用現(xiàn)有項(xiàng)目。body 列將存儲(chǔ)我們正在保存的筆記的內(nèi)容。歡迎你在這里選擇其他一些你覺得更好的術(shù)語。一些可能的選擇:內(nèi)容、消息、文本或標(biāo)題。事后當(dāng)然可以改變這一點(diǎn),但隨著時(shí)間的推移,越來越多的代碼引用這些特定術(shù)語,改變會(huì)越來越困難,所以試著選擇一個(gè)你能接受的并堅(jiān)持下去。

        我現(xiàn)在看到的大多數(shù)教程主要關(guān)注在服務(wù)器上存儲(chǔ)數(shù)據(jù)并通過某種 API 同步它。這個(gè)系列最終會(huì)那樣實(shí)現(xiàn),但像我們正在構(gòu)建的筆記應(yīng)用程序離線工作是非常重要的。盡早設(shè)置此限制允許我們考慮離線構(gòu)建——而不是試圖將其綁定到現(xiàn)有的云應(yīng)用程序。

        sqlite3[6] 是一個(gè)流行的數(shù)據(jù)庫庫,它將數(shù)據(jù)庫存儲(chǔ)在文件系統(tǒng)上的單個(gè)文件中。這對用戶來說很簡單,因?yàn)樗麄儾恍枰\(yùn)行單獨(dú)的數(shù)據(jù)庫服務(wù)器,并且如果需要,數(shù)據(jù)庫文件可以傳遞到其他系統(tǒng)。

        創(chuàng)建筆記表

        第一步是創(chuàng)建一個(gè)表來存放我們的應(yīng)用程序數(shù)據(jù)。我們將使用 rusqlite 庫來處理我們與 sqlite 數(shù)據(jù)庫的連接。你可以通過修改 Cargo.toml 來安裝它。

        Cargo.toml

        [package]
        name = "notes"
        version = "0.1.0"
        edition = "2021"

        # See more keys and their definitions at [https://doc.rust-lang.org/cargo/reference/manifest.html](https://doc.rust-lang.org/cargo/reference/manifest.html "https://doc.rust-lang.org/cargo/reference/manifest.html")

        [dependencies.rusqlite]
        version = "0.26.1"
        features = ["bundled"]

        這會(huì)添加 rusqlite 作為依賴項(xiàng),下次嘗試構(gòu)建時(shí)將安裝該依賴項(xiàng)。features = ["bundled"] 告訴包編譯 SQLite 。這在 Windows 上特別有用,因?yàn)樵?Windows 中查找系統(tǒng)庫非常困難。

        添加后,你現(xiàn)在可以訪問 main.rs 中的 rusqlite,將現(xiàn)有代碼替換為以下內(nèi)容:

        use?rusqlite::{Connection,?Result};

        fn?main()?->?Result<(),?Box<dyn?std::error::Error>>?{
        ??let?conn?=?Connection::open("notes.db")?;
        ??conn.execute(
        ????"create?table?if?not?exists?notes?(
        ??????id?integer?primary?key,
        ??????body?text?not?null?unique
        ????)"
        ,
        ????[],
        ??)?;
        ??
        ??Ok(())
        }

        現(xiàn)在你可以運(yùn)行 cargo run ,一旦它構(gòu)建完成,notes 程序就會(huì)運(yùn)行并立即退出。然后,你應(yīng)該會(huì)在當(dāng)前目錄中看到一個(gè)名為 notes.db 的文件。如果你安裝了 DB 瀏覽器,你可以打開這個(gè)文件并看到一個(gè)帶有 id 和 body 列的 notes 表。

        如果你再次運(yùn)行該程序,則不會(huì)發(fā)生任何事情。我們運(yùn)行的 SQL[7] 命令如下:

        create?table?if?not?exists?notes?(
        ??id?integer?primary?key,
        ??body?text?not?null?unique
        )

        指定僅在表不存在時(shí)創(chuàng)建表。當(dāng)我們用 let conn = Connection::open("notes.db")?; 打開連接時(shí),我們將 rusqlite 庫指向同一個(gè)數(shù)據(jù)庫文件,它能夠確定該表已經(jīng)創(chuàng)建。

        可選的為 SQLite 安裝數(shù)據(jù)庫瀏覽器

        我發(fā)現(xiàn)能夠直觀地確認(rèn)事情按預(yù)期工作很有幫助。此時(shí),你可以下載一個(gè)數(shù)據(jù)庫瀏覽器,讓你可以查看新創(chuàng)建的 notes.db 文件的內(nèi)容。

        你可以下載 SQLite 的數(shù)據(jù)庫瀏覽器[8]。安裝后打開它并單擊 Open Database 。

        notes.db 在 SQLite 的 DB Browser 中打開

        現(xiàn)在我們已經(jīng)創(chuàng)建了一個(gè)表并設(shè)置了我們的 schema,我們可以繼續(xù)添加我們的第一條筆記。

        03 CRUD——?jiǎng)?chuàng)建、讀取、更新、刪除

        在任何程序中開發(fā)新功能時(shí),我通常獨(dú)立處理 CRUD 首字母縮略詞的每個(gè)組件。對我來說最有意義的構(gòu)建順序是:

        1. Create

        2. Read

        3. Delete

        4. Update

        本教程的這一部分將僅涵蓋 create。下篇文章將討論其他的。

        04 創(chuàng)建

        Create 是第一位的,因?yàn)闆]有它,其他一切都沒有意義。在很多情況下,你的應(yīng)用程序只要可以創(chuàng)建就可以運(yùn)行。你顯然希望能夠完成其他工作,但他們的缺失不會(huì)影響你創(chuàng)建新項(xiàng)目。在我們的筆記示例中,你會(huì)看到,即使你剛剛添加了創(chuàng)建功能,你仍然擁有將筆記正確存儲(chǔ)到本地?cái)?shù)據(jù)庫的程序。如果這就是你能夠完成的全部工作,你仍然可以使用 DB Browser for SQLite 之類的工具打開 sqlite3 數(shù)據(jù)庫并在那里瀏覽所有筆記。

        在我們這里的小示例中,CRUD 的其余部分沒有太多內(nèi)容,但是在構(gòu)建更大的圖形用戶界面時(shí),僅演示和測試創(chuàng)建功能會(huì)很有用。

        要求

        對于筆記的創(chuàng)建,我只是希望能夠在終端中輸入我的筆記并按回車鍵。為了從命令行獲得輸入,我們將使用內(nèi)置的 std::io[9] 包。

        use?std::io;
        use?rusqlite::{Connection,?Result};

        fn?main()?->?Result<(),?Box<dyn?std::error::Error>>?{
        ??let?conn?=?Connection::open("notes.db")?;
        ??conn.execute(
        ????"create?table?if?not?exists?notes?(
        ??????id?integer?primary?key,
        ??????body?text?not?null?unique
        ????)"
        ,
        ????[],
        ??)?;

        ??let?mut?buffer?=?String::new();
        ??io::stdin().read_line(&mut?buffer)?;
        ??conn.execute("INSERT?INTO?notes?(body)?values?(?1)",?[buffer])?;

        ??Ok(())
        }

        我們可以再次使用 cargo run 運(yùn)行我們的應(yīng)用程序,你現(xiàn)在應(yīng)該看到它不會(huì)立即退出。你可以輸入任何你喜歡的消息,但 “hello world” 是標(biāo)準(zhǔn)的 “這東西工作正常嗎” 消息。按回車鍵后,程序應(yīng)該退出。

        提交第一個(gè)注釋后的示例輸出

        如果你在上面安裝了 DB Browser,你現(xiàn)在可以單擊 Browse Data,你將看到一行 id: 1 和 body: “hello world”(或你剛剛輸入的任何內(nèi)容)。

        DB 瀏覽器顯示“hello world”注釋

        這很好,但程序的目的是讓我們快速創(chuàng)建許多筆記。我們需要一些方法來使程序在提交第一個(gè)注釋后不會(huì)立即退出。

        為了實(shí)現(xiàn)這一點(diǎn),我們將使用一個(gè)循環(huán)——這里用一個(gè) while 循環(huán)。

        use?std::io;
        use?rusqlite::{Connection,?Result};

        fn?main()?->?Result<(),?Box<dyn?std::error::Error>>?{
        ??let?conn?=?Connection::open("notes.db")?;
        ??conn.execute(
        ????"create?table?if?not?exists?notes?(
        ??????id?integer?primary?key,
        ??????body?text?not?null?unique
        ????)"
        ,
        ????[],
        ??)?;

        ??let?mut?running?=?true;
        ??while?running?==?true?{
        ????let?mut?buffer?=?String::new();
        ????io::stdin().read_line(&mut?buffer)?;
        ????let?trimmed_body?=?buffer.trim();
        ????if?trimmed_body?==?""?{
        ??????running?=?false;
        ????}?else?{
        ??????conn.execute("INSERT?INTO?notes?(body)?values?(?1)",?[trimmed_body])?;
        ????}
        ??}

        ??Ok(())
        }

        為此,我們引入了一個(gè)名為 running 的布爾變量。當(dāng)我們啟動(dòng)程序時(shí),我們希望繼續(xù)接受輸入,因此我們將其初始化為 true。

        trimmed_body = buffer.trim(); 刪除輸入行末尾的任何空格。這是必要的,因?yàn)?read_line 返回帶有換行符 \n 的字符串。這在你可能會(huì)看到的大多數(shù)地方都是不可見的,但需要使 trimmed_body == "" 的相等檢查正確工作。作為一個(gè)額外的好處,.trim() 確保在我們存儲(chǔ)到數(shù)據(jù)庫之前刪除任何尾隨空格。

        我們現(xiàn)在可以再次運(yùn)行 cargo run,你現(xiàn)在應(yīng)該可以在不退出程序的情況下輸入一個(gè)又一個(gè)的字符。寫完筆記后,你可以在空行后再按 Enter 鍵(即按兩次 Enter 鍵),程序?qū)⑼顺觥?/p>

        單次運(yùn)行期間創(chuàng)建的多個(gè)筆記

        05 總結(jié)

        正如開頭提到的,這篇文章是一個(gè)較長系列的開始,該系列將介紹如何使用 Rust 為命令行構(gòu)建和設(shè)計(jì)筆記應(yīng)用程序。在過去的一年里,我使用了一個(gè)簡單的筆記應(yīng)用程序作為我用來試驗(yàn)新技術(shù)的項(xiàng)目。到目前為止,我已經(jīng)使用Swift iOS[10]、React Native for Android[11]、React[12] 和 Vanilla JavaScript 采用上述類似的方法構(gòu)建了筆記應(yīng)用程序(親切地稱為 engram[13])。

        我現(xiàn)在正在記錄這個(gè)過程,因?yàn)槭聦?shí)證明它非常成功地讓我了解我需要知道的東西。

        希望你通過本系列,自己動(dòng)手試驗(yàn),能夠?qū)?Rust 有更好的掌握。

        原文鏈接:https://devtails.xyz/how-to-build-a-note-taking-command-line-application-with-rust

        參考資料

        [1]

        engram: https://github.com/adamjberg/engram

        [2]

        cargo 是 Rust 包管理器: https://doc.rust-lang.org/cargo/

        [3]

        The Cargo Book: https://doc.rust-lang.org/cargo/reference/manifest.html

        [4]

        cargo run: https://doc.rust-lang.org/cargo/commands/cargo-run.html

        [5]

        請參閱 Cargo Book: https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html

        [6]

        sqlite3: https://www.sqlite.org/index.html

        [7]

        SQL: https://www.w3schools.com/sql/

        [8]

        下載 SQLite 的數(shù)據(jù)庫瀏覽器: https://sqlitebrowser.org/dl/

        [9]

        std::io: https://doc.rust-lang.org/std/io/index.html

        [10]

        Swift iOS: https://apps.apple.com/ca/app/engram/id1568952668

        [11]

        React Native for Android: https://play.google.com/store/apps/details?id=com.xyzdigital.engram

        [12]

        React: https://engram.xyzdigital.com/signup

        [13]

        engram: https://engramhq.xyz/




        往期推薦


        我是 polarisxu,北大碩士畢業(yè),曾在 360 等知名互聯(lián)網(wǎng)公司工作,10多年技術(shù)研發(fā)與架構(gòu)經(jīng)驗(yàn)!2012 年接觸 Go 語言并創(chuàng)建了 Go 語言中文網(wǎng)!著有《Go語言編程之旅》、開源圖書《Go語言標(biāo)準(zhǔn)庫》等。


        堅(jiān)持輸出技術(shù)(包括 Go、Rust 等技術(shù))、職場心得和創(chuàng)業(yè)感悟!歡迎關(guān)注「polarisxu」一起成長!也歡迎加我微信好友交流:gopherstudio

        瀏覽 87
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            免费黄色电影在线观看| 一级性爱视频| 高清欧美日韩第一摸| 骚逼日本| 国产成人高潮毛片| 特级丰满少妇免费观看| 九色PORNY国产成人| 亚洲欧洲中文字幕| 天天操天天干麻豆| 日韩无码123|