国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁 後端開發(fā) Golang 極簡(jiǎn)密碼管理器桌面應(yīng)用程式:進(jìn)軍 Golang 的 Wails 框架(第 2 部分)

極簡(jiǎn)密碼管理器桌面應(yīng)用程式:進(jìn)軍 Golang 的 Wails 框架(第 2 部分)

Dec 30, 2024 am 09:50 AM

各位程式設(shè)計(jì)師,大家好!在這個(gè)簡(jiǎn)短系列的第一部分中,我們看到了桌面應(yīng)用程式的建立和操作,用於儲(chǔ)存和加密使用 Wails 框架建立的密碼。我們還描述了 Go 後端以及如何將其綁定到前端。

在這一部分中,我們將處理使用者介面。正如我們?cè)谀瞧恼轮兴?,Wails 允許我們使用任何我們喜歡的 Web 框架,甚至 Vanilla JS,來建立我們的 GUI。正如我所說,Wails 的創(chuàng)作者似乎偏愛 Svelte,因?yàn)樗麄兛偸菍⑵渥鳛槭走x。當(dāng)我們要求使用 Svelte Typescript (wails init -n myproject -t svelte-ts) 建立專案時(shí),Wails CLI(目前版本)會(huì)使用 Svelte3 產(chǎn)生鷹架。正如我已經(jīng)告訴過您的,如果您更喜歡使用 Svelte5(及其新功能),我有一個(gè) bash 腳本可以自動(dòng)建立它(無論如何,您必須安裝 Wails CLI)。此外,它還添加了 Taildwindcss Daisyui,這在我看來是介面設(shè)計(jì)的完美組合。

事實(shí)是,我先使用Vanilla JsVue,然後使用React,甚至使用那個(gè)對(duì)許多人來說是React 的奇怪函式庫。 ??>HTMX(我必須說我喜歡??)。但是Svelte

讓你從一開始就愛上它,我不得不說,我是在嘗試Wails時(shí)第一次使用它的(我保證會(huì)繼續(xù)使用它......)。但是,儘管 Web 框架很舒服,但我們必須提醒後端開發(fā)人員,前端並不那麼容易? ! !

但是讓我們進(jìn)入正題吧。

I - 前端結(jié)構(gòu)概覽


如果您使用過任何 Web 框架,您很快就會(huì)認(rèn)識(shí)到 Wails CLI 在底層使用了 ViteJ:

...
.
├── index.html
├── package.json
├── package.json.md5
├── package-lock.json
├── postcss.config.js
├── README.md
├── src
│?? ├── App.svelte
│?? ├── assets
│?? │?? ├── fonts
│?? │?? │?? ├── nunito-v16-latin-regular.woff2
│?? │?? │?? └── OFL.txt
│?? │?? └── images
│?? │??     └── logo-universal.png
│?? ├── lib
│?? │?? ├── BackBtn.svelte
│?? │?? ├── BottomActions.svelte
│?? │?? ├── EditActions.svelte
│?? │?? ├── EntriesList.svelte
│?? │?? ├── Language.svelte
│?? │?? ├── popups
│?? │?? │?? ├── alert-icons.ts
│?? │?? │?? └── popups.ts
│?? │?? ├── ShowPasswordBtn.svelte
│?? │?? └── TopActions.svelte
│?? ├── locales
│?? │?? ├── en.json
│?? │?? └── es.json
│?? ├── main.ts
│?? ├── pages
│?? │?? ├── About.svelte
│?? │?? ├── AddPassword.svelte
│?? │?? ├── Details.svelte
│?? │?? ├── EditPassword.svelte
│?? │?? ├── Home.svelte
│?? │?? ├── Login.svelte
│?? │?? └── Settings.svelte
│?? ├── style.css
│?? └── vite-env.d.ts
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── wailsjs
    ├── go
    │?? ├── main
    │?? │?? ├── App.d.ts
    │?? │?? └── App.js
    │?? └── models.ts
    └── runtime
        ├── package.json
        ├── runtime.d.ts
        └── runtime.js

...

如果您使用過 Vite 產(chǎn)生的任何 Web 框架,您不會(huì)對(duì)其設(shè)定檔感到驚訝。這裡我使用 Svelte5 (加上 Taildwindcss Daisyui 的配置),這就是產(chǎn)生我自己的 bash 腳本的原因,正如我已經(jīng)告訴你的。我們也使用了TypeScript

,這樣會(huì)方便前端的開發(fā),所以你也可以看到它的配置。

但這個(gè)解釋中最重要的是wailsjs資料夾的內(nèi)容。這就是Wails 所做的編譯發(fā)揮其魔力的地方。 go 子資料夾是儲(chǔ)存必須與前端互動(dòng)的後端部分的「翻譯」為 Js/Ts
的方法的位置。例如,在 main/App.js(或其 TypeScript 版本 main/App.d.ts)中,有 App 結(jié)構(gòu)的所有匯出(公共)方法:

...
.
├── index.html
├── package.json
├── package.json.md5
├── package-lock.json
├── postcss.config.js
├── README.md
├── src
│?? ├── App.svelte
│?? ├── assets
│?? │?? ├── fonts
│?? │?? │?? ├── nunito-v16-latin-regular.woff2
│?? │?? │?? └── OFL.txt
│?? │?? └── images
│?? │??     └── logo-universal.png
│?? ├── lib
│?? │?? ├── BackBtn.svelte
│?? │?? ├── BottomActions.svelte
│?? │?? ├── EditActions.svelte
│?? │?? ├── EntriesList.svelte
│?? │?? ├── Language.svelte
│?? │?? ├── popups
│?? │?? │?? ├── alert-icons.ts
│?? │?? │?? └── popups.ts
│?? │?? ├── ShowPasswordBtn.svelte
│?? │?? └── TopActions.svelte
│?? ├── locales
│?? │?? ├── en.json
│?? │?? └── es.json
│?? ├── main.ts
│?? ├── pages
│?? │?? ├── About.svelte
│?? │?? ├── AddPassword.svelte
│?? │?? ├── Details.svelte
│?? │?? ├── EditPassword.svelte
│?? │?? ├── Home.svelte
│?? │?? ├── Login.svelte
│?? │?? └── Settings.svelte
│?? ├── style.css
│?? └── vite-env.d.ts
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── wailsjs
    ├── go
    │?? ├── main
    │?? │?? ├── App.d.ts
    │?? │?? └── App.js
    │?? └── models.ts
    └── runtime
        ├── package.json
        ├── runtime.d.ts
        └── runtime.js

...

他們都回傳一個(gè)承諾。如果Promise「包裝」了一些用作返回類型的Go 結(jié)構(gòu),或者相應(yīng)的函數(shù)採用參數(shù)類型,則會(huì)有一個(gè)模組(models.ts,在本例中為類型,因?yàn)槲覀兪褂肨ypeScript),其中包含與Go對(duì)應(yīng)的類別命名空間中的結(jié)構(gòu)及其建構(gòu)函數(shù)。

此外,runtime 子資料夾包含 Go 執(zhí)行時(shí)間套件中的所有方法,這些方法允許我們分別操作視窗以及從後端偵聽或發(fā)出的事件。

src 資料夾包含將由 Vite 編譯的文件,並將它們保存在「frontend/dist」中(並嵌入到最終的可執(zhí)行檔中),就像在任何 Web 應(yīng)用程式中一樣。請(qǐng)注意,由於我們使用 Tailwindcss,style.css 包含基本的 Tailwind 配置以及我們需要使用的任何 CSS 類別。此外,作為介面使用網(wǎng)路技術(shù)的優(yōu)勢(shì),我們可以輕鬆地使用一種或多種字體(資料夾資產(chǎn)/字體)或交換它們。

為了完成這個(gè)概述,請(qǐng)注意,當(dāng)我們?cè)陂_發(fā)模式(wails dev)下編譯時(shí),除了允許我們熱重載之外,我們不僅可以觀察所做的更改(無論是在後端還是在前端)應(yīng)用程式視窗本身,也透過位址http://localhost:34115 在Web 瀏覽器中,因?yàn)閃eb 伺服器已啟動(dòng)。這允許您使用您最喜歡的瀏覽器開發(fā)擴(kuò)充功能。雖然必須說Wails本人為我們提供了一些非常有用的開發(fā)工具,但是當(dāng)我們右鍵單擊應(yīng)用程式視窗(僅在開發(fā)模式下)並選擇“Inspect Element”時(shí):

A minimalist password manager desktop app: a foray into Golang

II - 現(xiàn)在…深入研究 HTML、CSS 和 JavaScript?


// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH ? MODIWL
// This file is automatically generated. DO NOT EDIT
import {models} from '../models';

export function AddPasswordEntry(arg1:string,arg2:string,arg3:string):Promise<string>;

export function CheckMasterPassword(arg1:string):Promise<boolean>;

export function DeleteEntry(arg1:string):Promise<void>;

export function Drop():Promise<void>;

export function GetAllEntries():Promise<Array<models.PasswordEntry>>;

export function GetEntryById(arg1:string):Promise<models.PasswordEntry>;

export function GetLanguage():Promise<string>;

export function GetMasterPassword():Promise<boolean>;

export function GetPasswordCount():Promise<number>;

export function SaveLanguage(arg1:string):Promise<void>;

export function SaveMasterPassword(arg1:string):Promise<string>;

export function UpdateEntry(arg1:models.PasswordEntry):Promise<boolean>;

如你所見,我已經(jīng)在 Svelte 中加入了 4 個(gè) JavaScript 套件(除了已經(jīng)提到的 Tailwindcss Daisyui):

  • svelte-copy,可以更輕鬆地將使用者名稱和密碼複製到剪貼簿。
  • svelte-i18n,用於 i18n 處理,即允許使用者更改應(yīng)用程式的語言。
  • svelte-spa-router,Svelte 的一個(gè)小型路由庫,它可以更輕鬆地更改應(yīng)用程式視窗中的視圖,因?yàn)樵谶@種情況下,使用由SvelteKit。
  • sweetalert2,基本上用它來輕鬆快速地建立模態(tài)框/對(duì)話框。

每個(gè) SPA 的入口點(diǎn)都是 main.js(或 main.ts)文件,所以讓我們從它開始:

...
.
├── index.html
├── package.json
├── package.json.md5
├── package-lock.json
├── postcss.config.js
├── README.md
├── src
│?? ├── App.svelte
│?? ├── assets
│?? │?? ├── fonts
│?? │?? │?? ├── nunito-v16-latin-regular.woff2
│?? │?? │?? └── OFL.txt
│?? │?? └── images
│?? │??     └── logo-universal.png
│?? ├── lib
│?? │?? ├── BackBtn.svelte
│?? │?? ├── BottomActions.svelte
│?? │?? ├── EditActions.svelte
│?? │?? ├── EntriesList.svelte
│?? │?? ├── Language.svelte
│?? │?? ├── popups
│?? │?? │?? ├── alert-icons.ts
│?? │?? │?? └── popups.ts
│?? │?? ├── ShowPasswordBtn.svelte
│?? │?? └── TopActions.svelte
│?? ├── locales
│?? │?? ├── en.json
│?? │?? └── es.json
│?? ├── main.ts
│?? ├── pages
│?? │?? ├── About.svelte
│?? │?? ├── AddPassword.svelte
│?? │?? ├── Details.svelte
│?? │?? ├── EditPassword.svelte
│?? │?? ├── Home.svelte
│?? │?? ├── Login.svelte
│?? │?? └── Settings.svelte
│?? ├── style.css
│?? └── vite-env.d.ts
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── wailsjs
    ├── go
    │?? ├── main
    │?? │?? ├── App.d.ts
    │?? │?? └── App.js
    │?? └── models.ts
    └── runtime
        ├── package.json
        ├── runtime.d.ts
        └── runtime.js

...

我突出顯示了添加到由 Wails CLI 產(chǎn)生的框架中的內(nèi)容。 svelte-i18n 庫要求在main.js/ts 文件中註冊(cè)包含翻譯的JSON 文件,同時(shí)設(shè)定fallback/initial 語言(儘管我們'你會(huì)看到,稍後將根據(jù)使用者選擇的偏好進(jìn)行操作)。包含翻譯的 JSON 檔案的格式為:

// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH ? MODIWL
// This file is automatically generated. DO NOT EDIT
import {models} from '../models';

export function AddPasswordEntry(arg1:string,arg2:string,arg3:string):Promise<string>;

export function CheckMasterPassword(arg1:string):Promise<boolean>;

export function DeleteEntry(arg1:string):Promise<void>;

export function Drop():Promise<void>;

export function GetAllEntries():Promise<Array<models.PasswordEntry>>;

export function GetEntryById(arg1:string):Promise<models.PasswordEntry>;

export function GetLanguage():Promise<string>;

export function GetMasterPassword():Promise<boolean>;

export function GetPasswordCount():Promise<number>;

export function SaveLanguage(arg1:string):Promise<void>;

export function SaveMasterPassword(arg1:string):Promise<string>;

export function UpdateEntry(arg1:models.PasswordEntry):Promise<boolean>;

我發(fā)現(xiàn)這個(gè)函式庫的系統(tǒng)對(duì)於促進(jìn) Svelte 應(yīng)用程式的翻譯非常簡(jiǎn)單和方便(您可以查閱其文件以了解更多詳細(xì)資訊):

/* package.json */
...
},
  "dependencies": {
    "svelte-copy": "^2.0.0",
    "svelte-i18n": "^4.0.1",
    "svelte-spa-router": "^4.0.1",
    "sweetalert2": "^11.14.5"
  }
...

您也可以使用像這樣的網(wǎng)站,它將幫助您將 JSON 檔案翻譯成不同的語言。然而,問題是,當(dāng)您使用 $format 填充 .svelte 檔案時(shí),您必須手動(dòng)追蹤它們,這是乏味且容易出錯(cuò)的。我不知道有什麼方法可以自動(dòng)完成這項(xiàng)任務(wù),如果有人知道,我會(huì)很感興趣,如果你能讓我知道? ……否則,我必須想出某種腳本來完成這項(xiàng)工作。

與任何 Svelte 應(yīng)用程式一樣,建立介面的下一步是 App.svelte 檔案:

/* main.ts */

import { mount } from 'svelte'
import './style.css'
import App from './App.svelte'
import { addMessages, init } from "svelte-i18n"; // ? ?
import en from './locales/en.json'; // ? ?
import es from './locales/es.json'; // ? ?

addMessages('en', en); // ? ?
addMessages('es', es); // ? ?

init({
  fallbackLocale: 'en', // ? ?
  initialLocale: 'en', // ? ?
});

const app = mount(App, {
  target: document.getElementById('app')!,
})

export default app

這裡我們使用 GetMasterPassword,它是編譯應(yīng)用程式時(shí)自動(dòng)產(chǎn)生的 綁定,並被宣告為 struct App 的公共方法(請(qǐng)參閱本系列的第一部分)。該函數(shù)查詢資料庫,如果其中註冊(cè)了主密碼,它會(huì)認(rèn)為使用者已經(jīng)註冊(cè)(它會(huì)傳回一個(gè)包含布林值的承諾),要求他輸入所述密碼以允許他存取其餘內(nèi)容的意見。如果資料庫中沒有主密碼,則該使用者被視為“新”,要求他產(chǎn)生自己的密碼以首次進(jìn)入應(yīng)用程式。

最後,在安裝 Login.svelte 元件時(shí),我們做了一些對(duì)應(yīng)用程式的其餘部分很重要的事情。儘管 svelte-i18n 庫強(qiáng)制我們聲明初始語言代碼,但正如我們已經(jīng)看到的,在安裝 Login.svelte 時(shí),我們要求資料庫(使用 GetLanguage 綁定)檢查是否保存了語言代碼。如果資料庫傳回空字串,即沒有配置為使用者首選項(xiàng)的語言,svelte-i18n 將使用配置為initialLocale 的值。如果配置了一種語言,則將設(shè)定該語言(locale.set(result);) 並發(fā)出「change_titles」事件,標(biāo)題列和應(yīng)用程式本機(jī)對(duì)話方塊的翻譯標(biāo)題將傳遞到該事件供後端處理:

/* frontend/src/locales/en.json */

{
    "language": "Language",
    "app_title": "Nu-i uita ? minimalist password store",
    "select_directory": "Select the directory where to save the data export",
    "select_file": "Select the backup file to import",
    "master_password": "Master Password ?",
    "generate": "Generate",
    "insert": "Insert",
    "login": "Login",
    ...
}


/* frontend/src/locales/es.json */

{
    "language": "Idioma",
    "app_title": "Nu-i uita ? almacén de contrase?as minimalista",
    "select_directory": "Selecciona el directorio donde guardar los datos exportados",
    "select_file": "Selecciona el archivo de respaldo que deseas importar",
    "master_password": "Contrase?a Maestra ?",
    "generate": "Generar",
    "insert": "Insertar",
    "login": "Inciar sesión",
    ...
}

以下是處理登入的邏輯:

...
.
├── index.html
├── package.json
├── package.json.md5
├── package-lock.json
├── postcss.config.js
├── README.md
├── src
│?? ├── App.svelte
│?? ├── assets
│?? │?? ├── fonts
│?? │?? │?? ├── nunito-v16-latin-regular.woff2
│?? │?? │?? └── OFL.txt
│?? │?? └── images
│?? │??     └── logo-universal.png
│?? ├── lib
│?? │?? ├── BackBtn.svelte
│?? │?? ├── BottomActions.svelte
│?? │?? ├── EditActions.svelte
│?? │?? ├── EntriesList.svelte
│?? │?? ├── Language.svelte
│?? │?? ├── popups
│?? │?? │?? ├── alert-icons.ts
│?? │?? │?? └── popups.ts
│?? │?? ├── ShowPasswordBtn.svelte
│?? │?? └── TopActions.svelte
│?? ├── locales
│?? │?? ├── en.json
│?? │?? └── es.json
│?? ├── main.ts
│?? ├── pages
│?? │?? ├── About.svelte
│?? │?? ├── AddPassword.svelte
│?? │?? ├── Details.svelte
│?? │?? ├── EditPassword.svelte
│?? │?? ├── Home.svelte
│?? │?? ├── Login.svelte
│?? │?? └── Settings.svelte
│?? ├── style.css
│?? └── vite-env.d.ts
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── wailsjs
    ├── go
    │?? ├── main
    │?? │?? ├── App.d.ts
    │?? │?? └── App.js
    │?? └── models.ts
    └── runtime
        ├── package.json
        ├── runtime.d.ts
        └── runtime.js

...

簡(jiǎn)單地說:newPassword,綁定到獲取用戶輸入內(nèi)容的輸入的狀態(tài),首先由onLogin 檢查它是否至少有6 個(gè)字符,並且它們都是ASCII 字符,即,通過這個(gè)小函數(shù)const isAscii = (str: string): boolean => 它們只有1 個(gè)位元組長(zhǎng)(請(qǐng)參閱本系列第一部分的原因)。 /^[x00-x7F] $/.test(str);.如果檢查失敗,函數(shù)將傳回並向使用者顯示警告 toast。之後,如果資料庫中沒有保存主密碼(isLogin = false),則SaveMasterPassword 函數(shù)將保存使用者輸入的任何內(nèi)容(Wails 產(chǎn)生的綁定);如果Promise 成功解析(傳回uuid 字串作為資料庫中儲(chǔ)存的記錄的Id),使用者將被svelte-spa-router 帶到主頁視圖庫的推送方法。相反,如果密碼通過了長(zhǎng)度檢查,且不存在非ASCII 字符,且資料庫中存在主密碼(isLogin = true),則CheckMasterPassword 函數(shù)將根據(jù)儲(chǔ)存的密碼驗(yàn)證其身份,或?qū)⑹褂谜邘У街饕晥D(promise 為true 解決)或顯示toast 表示輸入的密碼不正確。

應(yīng)用程式的中心視圖,同時(shí)也是最複雜的視圖是主頁視圖。它的HTML 實(shí)際上分為3 個(gè)元件:一個(gè)帶有搜尋輸入的頂部按鈕列(TopActions 元件)、一個(gè)底部按鈕欄(BottomActions 元件)以及一個(gè)中心區(qū)域,其中使用以下命令顯示已儲(chǔ)存密碼條目的總數(shù)或這些項(xiàng)目的清單:可捲動(dòng)視窗(EntriesList 元件):

// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH ? MODIWL
// This file is automatically generated. DO NOT EDIT
import {models} from '../models';

export function AddPasswordEntry(arg1:string,arg2:string,arg3:string):Promise<string>;

export function CheckMasterPassword(arg1:string):Promise<boolean>;

export function DeleteEntry(arg1:string):Promise<void>;

export function Drop():Promise<void>;

export function GetAllEntries():Promise<Array<models.PasswordEntry>>;

export function GetEntryById(arg1:string):Promise<models.PasswordEntry>;

export function GetLanguage():Promise<string>;

export function GetMasterPassword():Promise<boolean>;

export function GetPasswordCount():Promise<number>;

export function SaveLanguage(arg1:string):Promise<void>;

export function SaveMasterPassword(arg1:string):Promise<string>;

export function UpdateEntry(arg1:models.PasswordEntry):Promise<boolean>;

也就是說,它使搜尋狀態(tài)(searchTerms)成為一個(gè)空字串,這樣如果有任何搜尋詞,它就會(huì)被重置,從而顯示整個(gè)列表。另一方面,它會(huì)切換 showList 狀態(tài)(props TopActions 中的 isEntriesList),以便父元件顯示或隱藏清單。

如我們?cè)谏蠄D中所看到的,兩個(gè)子元件與父元件的 searchTerms 狀態(tài)共用相同的 props。 TopActions 元件會(huì)擷取使用者的輸入,並將其作為狀態(tài)傳遞給父元件 Home,而父元件 Home 又將其作為 props 傳遞給其子元件 EntriesList。

顯示完整清單或按使用者輸入的搜尋字詞過濾的清單的主要邏輯按預(yù)期由 EntriesList 元件執(zhí)行:

...
.
├── index.html
├── package.json
├── package.json.md5
├── package-lock.json
├── postcss.config.js
├── README.md
├── src
│?? ├── App.svelte
│?? ├── assets
│?? │?? ├── fonts
│?? │?? │?? ├── nunito-v16-latin-regular.woff2
│?? │?? │?? └── OFL.txt
│?? │?? └── images
│?? │??     └── logo-universal.png
│?? ├── lib
│?? │?? ├── BackBtn.svelte
│?? │?? ├── BottomActions.svelte
│?? │?? ├── EditActions.svelte
│?? │?? ├── EntriesList.svelte
│?? │?? ├── Language.svelte
│?? │?? ├── popups
│?? │?? │?? ├── alert-icons.ts
│?? │?? │?? └── popups.ts
│?? │?? ├── ShowPasswordBtn.svelte
│?? │?? └── TopActions.svelte
│?? ├── locales
│?? │?? ├── en.json
│?? │?? └── es.json
│?? ├── main.ts
│?? ├── pages
│?? │?? ├── About.svelte
│?? │?? ├── AddPassword.svelte
│?? │?? ├── Details.svelte
│?? │?? ├── EditPassword.svelte
│?? │?? ├── Home.svelte
│?? │?? ├── Login.svelte
│?? │?? └── Settings.svelte
│?? ├── style.css
│?? └── vite-env.d.ts
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── wailsjs
    ├── go
    │?? ├── main
    │?? │?? ├── App.d.ts
    │?? │?? └── App.js
    │?? └── models.ts
    └── runtime
        ├── package.json
        ├── runtime.d.ts
        └── runtime.js

...

正如我們所說,收到 2 個(gè) props(listCounter 和 search)並維護(hù)一個(gè)狀態(tài)(讓條目:models.PasswordEntry[] = $state([]);)。當(dāng)根據(jù)使用者的請(qǐng)求安裝該元件時(shí),後端會(huì)被要求提供已儲(chǔ)存密碼條目的完整清單。如果沒有搜尋字詞,則將其儲(chǔ)存在狀態(tài)中;如果有,則對(duì)獲得的陣列進(jìn)行簡(jiǎn)單過濾,並將其保存在狀態(tài):

// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH ? MODIWL
// This file is automatically generated. DO NOT EDIT
import {models} from '../models';

export function AddPasswordEntry(arg1:string,arg2:string,arg3:string):Promise<string>;

export function CheckMasterPassword(arg1:string):Promise<boolean>;

export function DeleteEntry(arg1:string):Promise<void>;

export function Drop():Promise<void>;

export function GetAllEntries():Promise<Array<models.PasswordEntry>>;

export function GetEntryById(arg1:string):Promise<models.PasswordEntry>;

export function GetLanguage():Promise<string>;

export function GetMasterPassword():Promise<boolean>;

export function GetPasswordCount():Promise<number>;

export function SaveLanguage(arg1:string):Promise<void>;

export function SaveMasterPassword(arg1:string):Promise<string>;

export function UpdateEntry(arg1:models.PasswordEntry):Promise<boolean>;

在顯示的清單中,使用者可以執(zhí)行 2 個(gè)操作。第一個(gè)是顯示條目的詳細(xì)信息,當(dāng)他點(diǎn)擊相應(yīng)的按鈕時(shí)執(zhí)行:onclick={() =>推送(`/details/${entry.Id}`)}?;旧?,我們呼叫路由庫的 Push 方法將使用者帶到詳細(xì)資訊視圖,但傳遞與相關(guān)項(xiàng)目相對(duì)應(yīng)的 Id 參數(shù)。

使用者可以執(zhí)行的另一個(gè)操作是從清單中刪除項(xiàng)目。如果他單擊相應(yīng)的按鈕,將顯示一個(gè)確認(rèn)彈出窗口,並呼叫 showAlert 函數(shù)。函數(shù)依序呼叫 showWarning,它實(shí)際上是 sweetalert2 函式庫的抽象層(呼叫 sweetalert2 函式庫的所有函數(shù)都在 frontend/src/lib/popups/popups.ts 中)。如果使用者確認(rèn)刪除操作,則呼叫DeleteEntry綁定(將其從資料庫中刪除),反過來,如果它傳回的promise得到解析,則呼叫deleteItem(將其從儲(chǔ)存在條目狀態(tài)的陣列中刪除) :

/* package.json */
...
},
  "dependencies": {
    "svelte-copy": "^2.0.0",
    "svelte-i18n": "^4.0.1",
    "svelte-spa-router": "^4.0.1",
    "sweetalert2": "^11.14.5"
  }
...

主頁視圖的另一個(gè)元件(BottomActions)簡(jiǎn)單得多:它不會(huì)接收 props 並且僅限於將使用者重新導(dǎo)向到各種視圖(Settings、About 或 AddPassword)。

AddPassword 和 EditPassword 視圖的邏輯非常相似,也與 Login 視圖類似。兩者都不允許使用者在文字輸入的開頭和結(jié)尾輸入空格,並遵循與登入視圖相同的策略,要求密碼長(zhǎng)度至少為 6 個(gè) ASCII 字元?;旧希鼈兊呐c眾不同之處在於它們調(diào)用與需要執(zhí)行的操作相關(guān)的由 Wails 產(chǎn)生的連結(jié):

/* main.ts */

import { mount } from 'svelte'
import './style.css'
import App from './App.svelte'
import { addMessages, init } from "svelte-i18n"; // ? ?
import en from './locales/en.json'; // ? ?
import es from './locales/es.json'; // ? ?

addMessages('en', en); // ? ?
addMessages('es', es); // ? ?

init({
  fallbackLocale: 'en', // ? ?
  initialLocale: 'en', // ? ?
});

const app = mount(App, {
  target: document.getElementById('app')!,
})

export default app

另一個(gè)有點(diǎn)複雜的視圖是「設(shè)定」。它有一個(gè)語言元件,它從其父元件(設(shè)定)接收 props languageName:

/* frontend/src/locales/en.json */

{
    "language": "Language",
    "app_title": "Nu-i uita ? minimalist password store",
    "select_directory": "Select the directory where to save the data export",
    "select_file": "Select the backup file to import",
    "master_password": "Master Password ?",
    "generate": "Generate",
    "insert": "Insert",
    "login": "Login",
    ...
}


/* frontend/src/locales/es.json */

{
    "language": "Idioma",
    "app_title": "Nu-i uita ? almacén de contrase?as minimalista",
    "select_directory": "Selecciona el directorio donde guardar los datos exportados",
    "select_file": "Selecciona el archivo de respaldo que deseas importar",
    "master_password": "Contrase?a Maestra ?",
    "generate": "Generar",
    "insert": "Insertar",
    "login": "Inciar sesión",
    ...
}

此元件的 HTML 是一個(gè)處理使用者語言選擇的 select。在其 onchange 事件中,它接收一個(gè)函數(shù) (handleChange),該函數(shù)執(zhí)行 3 件事:

  • 使用 svelte-i18n 函式庫設(shè)定前端語言
  • 發(fā)出一個(gè)事件(“change_titles”),以便Wails運(yùn)行時(shí)更改應(yīng)用程式標(biāo)題列的標(biāo)題以及相關(guān)的選擇目錄選擇檔案對(duì)話框的標(biāo)題到上一個(gè)操作
  • 將使用者選擇的語言保存在資料庫中,以便下次啟動(dòng)應(yīng)用程式時(shí),它將開啟配置為該語言的。

傳回「設(shè)定」視圖,其整個(gè)操作由一系列傳送到後端或從後端接收的事件控制。最簡(jiǎn)單的是退出按鈕:當(dāng)使用者點(diǎn)擊它時(shí),會(huì)在後端觸發(fā)並偵聽退出事件,然後應(yīng)用程式關(guān)閉(onclick={() => EventsEmit("quit")})。 提示 通知使用者 Escape 鍵(快速鍵)執(zhí)行相同的操作,正如我們已經(jīng)解釋過的。

重置按鈕呼叫顯示彈出視窗的函數(shù):

...
.
├── index.html
├── package.json
├── package.json.md5
├── package-lock.json
├── postcss.config.js
├── README.md
├── src
│?? ├── App.svelte
│?? ├── assets
│?? │?? ├── fonts
│?? │?? │?? ├── nunito-v16-latin-regular.woff2
│?? │?? │?? └── OFL.txt
│?? │?? └── images
│?? │??     └── logo-universal.png
│?? ├── lib
│?? │?? ├── BackBtn.svelte
│?? │?? ├── BottomActions.svelte
│?? │?? ├── EditActions.svelte
│?? │?? ├── EntriesList.svelte
│?? │?? ├── Language.svelte
│?? │?? ├── popups
│?? │?? │?? ├── alert-icons.ts
│?? │?? │?? └── popups.ts
│?? │?? ├── ShowPasswordBtn.svelte
│?? │?? └── TopActions.svelte
│?? ├── locales
│?? │?? ├── en.json
│?? │?? └── es.json
│?? ├── main.ts
│?? ├── pages
│?? │?? ├── About.svelte
│?? │?? ├── AddPassword.svelte
│?? │?? ├── Details.svelte
│?? │?? ├── EditPassword.svelte
│?? │?? ├── Home.svelte
│?? │?? ├── Login.svelte
│?? │?? └── Settings.svelte
│?? ├── style.css
│?? └── vite-env.d.ts
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── wailsjs
    ├── go
    │?? ├── main
    │?? │?? ├── App.d.ts
    │?? │?? └── App.js
    │?? └── models.ts
    └── runtime
        ├── package.json
        ├── runtime.d.ts
        └── runtime.js

...

如果使用者接受該操作,則會(huì)呼叫Drop 綁定,這會(huì)清除資料庫中的所有collections,如果它傳回的Promise 已解析,則會(huì)將使用者傳送至Login 視圖,顯示指示操作成功的模式。

剩下的另外兩個(gè)操作彼此類似,所以讓我們看看導(dǎo)入資料。

如果使用者點(diǎn)擊對(duì)應(yīng)的按鈕,則會(huì)發(fā)出事件(onclick={() => EventsEmit("import_data")}),該事件在後端監(jiān)聽。收到後,將開啟本機(jī)選擇檔案對(duì)話方塊以允許使用者選擇備份檔案。如果使用者選擇文件,包含路徑(fileLocation)的變數(shù)將不包含空字串,這將在後端觸發(fā)一個(gè)事件(“enter_password”),該事件現(xiàn)在在前端偵聽,然後顯示新的彈出視窗詢問匯出時(shí)使用的主密碼。同樣,前端將發(fā)出另一個(gè)事件(「密碼」),其中攜帶使用者輸入的主密碼。當(dāng)後端接收到這個(gè)新事件時(shí),會(huì)執(zhí)行 Db 套件的 ImportDump 方法,該方法執(zhí)行從使用者選擇的備份檔案中讀取和還原 DB 中的資料的工作。結(jié)果,發(fā)出一個(gè)新事件(“imported_data”),該事件將其執(zhí)行結(jié)果(成功或不成功)作為附加資料攜帶。前端收到事件後只需執(zhí)行 2 個(gè)任務(wù):

  • 如果結(jié)果成功,請(qǐng)?jiān)O(shè)定備份檔案中儲(chǔ)存的語言並顯示指示操作成功的模式
  • 如果由於某種原因無法完成匯入,請(qǐng)顯示錯(cuò)誤及其原因。

所有這些在程式碼邏輯中比用文字解釋要容易得多? :

...
.
├── index.html
├── package.json
├── package.json.md5
├── package-lock.json
├── postcss.config.js
├── README.md
├── src
│?? ├── App.svelte
│?? ├── assets
│?? │?? ├── fonts
│?? │?? │?? ├── nunito-v16-latin-regular.woff2
│?? │?? │?? └── OFL.txt
│?? │?? └── images
│?? │??     └── logo-universal.png
│?? ├── lib
│?? │?? ├── BackBtn.svelte
│?? │?? ├── BottomActions.svelte
│?? │?? ├── EditActions.svelte
│?? │?? ├── EntriesList.svelte
│?? │?? ├── Language.svelte
│?? │?? ├── popups
│?? │?? │?? ├── alert-icons.ts
│?? │?? │?? └── popups.ts
│?? │?? ├── ShowPasswordBtn.svelte
│?? │?? └── TopActions.svelte
│?? ├── locales
│?? │?? ├── en.json
│?? │?? └── es.json
│?? ├── main.ts
│?? ├── pages
│?? │?? ├── About.svelte
│?? │?? ├── AddPassword.svelte
│?? │?? ├── Details.svelte
│?? │?? ├── EditPassword.svelte
│?? │?? ├── Home.svelte
│?? │?? ├── Login.svelte
│?? │?? └── Settings.svelte
│?? ├── style.css
│?? └── vite-env.d.ts
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── wailsjs
    ├── go
    │?? ├── main
    │?? │?? ├── App.d.ts
    │?? │?? └── App.js
    │?? └── models.ts
    └── runtime
        ├── package.json
        ├── runtime.d.ts
        └── runtime.js

...

值得一提的是,在前端註冊(cè)偵聽器的 Wails 運(yùn)行時(shí)函數(shù) (EventsOn) 傳回一個(gè)函數(shù),該函數(shù)在呼叫時(shí)會(huì)取消所述偵聽器。當(dāng)組件被銷毀時(shí),取消所述監(jiān)聽器是很方便的。與React 類似,onMount 鉤子可以透過讓監(jiān)聽器傳回一個(gè)清理函數(shù)來「清理」它們,在這種情況下,該函數(shù)將呼叫EventsOn 傳回的所有函數(shù),我們已採取預(yù)防措施將其保存在單獨(dú)的文件中。變數(shù):

// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH ? MODIWL
// This file is automatically generated. DO NOT EDIT
import {models} from '../models';

export function AddPasswordEntry(arg1:string,arg2:string,arg3:string):Promise<string>;

export function CheckMasterPassword(arg1:string):Promise<boolean>;

export function DeleteEntry(arg1:string):Promise<void>;

export function Drop():Promise<void>;

export function GetAllEntries():Promise<Array<models.PasswordEntry>>;

export function GetEntryById(arg1:string):Promise<models.PasswordEntry>;

export function GetLanguage():Promise<string>;

export function GetMasterPassword():Promise<boolean>;

export function GetPasswordCount():Promise<number>;

export function SaveLanguage(arg1:string):Promise<void>;

export function SaveMasterPassword(arg1:string):Promise<string>;

export function UpdateEntry(arg1:models.PasswordEntry):Promise<boolean>;

為了完成對(duì)我們應(yīng)用程式前端部分的審查,只需介紹一下「關(guān)於」組件即可。這幾乎沒有邏輯,因?yàn)樗鼉H限於顯示有關(guān)應(yīng)用程式的信息,就像常見的 about 一樣。然而,應(yīng)該說,正如我們所看到的,該視圖顯示了指向應(yīng)用程式儲(chǔ)存庫的連結(jié)。顯然,在普通網(wǎng)頁中,錨標(biāo)記() 將使我們導(dǎo)航到相應(yīng)的鏈接,但在桌面應(yīng)用程式中,如果Wails 在運(yùn)行時(shí)沒有為此提供特定函數(shù)(BrowserOpenURL),則不會(huì)發(fā)生這種情況:

/* package.json */
...
},
  "dependencies": {
    "svelte-copy": "^2.0.0",
    "svelte-i18n": "^4.0.1",
    "svelte-spa-router": "^4.0.1",
    "sweetalert2": "^11.14.5"
  }
...

這會(huì)將二進(jìn)位檔案建置到 build/bin 資料夾中。但是,要選擇其他建置選項(xiàng)或執(zhí)行交叉編譯,您可能需要查看 Wails CLI 文件。

對(duì)於這個(gè)應(yīng)用程序,我想我已經(jīng)在本系列的第一部分中提到過,我只關(guān)注Windows和Linux的編譯。為了以舒適的方式執(zhí)行這些任務(wù)(由於測(cè)試,這些任務(wù)是重複的),我創(chuàng)建了一些小腳本和一個(gè)「協(xié)調(diào)」它們的 Makefile。

make create-bundles 指令為L(zhǎng)inux 版本建立一個(gè).tar.xz 壓縮文件,其中包含應(yīng)用程式和一個(gè)充當(dāng)安裝執(zhí)行檔的「安裝程式」的Makefile,一個(gè)用於在開始功能表以及對(duì)應(yīng)的應(yīng)用程式圖示。對(duì)於 Windows 版本,二進(jìn)位檔案只是在名為 dist/ 的資料夾中壓縮為 .zip。但是,如果您喜歡跨平臺(tái)自動(dòng)構(gòu)建,Wails 有一個(gè) Github Actions,允許您上傳(預(yù)設(shè)選項(xiàng))生成的工件到您的儲(chǔ)存庫。

請(qǐng)注意,如果您在運(yùn)行時(shí)使用make create-bundles 命令,它將呼叫Wails 命令wails build -clean -upx (對(duì)於Linux)或wails build -skipbindings -s -platform windows/amd64 - upx(對(duì)於Windows )。 -upx 標(biāo)誌是指使用您應(yīng)該安裝在電腦上的

UPX 實(shí)用程式來壓縮二進(jìn)位檔案??蓤?zhí)行檔案體積小的部分秘密是由於該實(shí)用程式所做的出色的壓縮工作。

最後,請(qǐng)注意,建置腳本會(huì)自動(dòng)將目前儲(chǔ)存庫標(biāo)籤新增至「關(guān)於」視圖,並在建置後將其值還原為預(yù)設(shè)值 (DEV_VERSION)。

??!這兩篇文章比我想像的還要長(zhǎng)!但我希望您喜歡它們,最重要的是,它們可以幫助您思考新專案。在程式設(shè)計(jì)中學(xué)習(xí)一些東西就像這樣...

請(qǐng)記住,您可以在此 GitHub 儲(chǔ)存庫中找到所有應(yīng)用程式程式碼。

我相信我會(huì)在其他貼文中見到你。編碼愉快? ! !

以上是極簡(jiǎn)密碼管理器桌面應(yīng)用程式:進(jìn)軍 Golang 的 Wails 框架(第 2 部分)的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

您如何在GO中有效地處理JSON編碼和解碼? 您如何在GO中有效地處理JSON編碼和解碼? Jun 11, 2025 am 12:02 AM

在Go中有效處理JSON需關(guān)注結(jié)構(gòu)標(biāo)籤、可選字段及動(dòng)態(tài)解析等問題。使用struct標(biāo)籤可自定義JSON鍵名,如json:"name";確保字段導(dǎo)出以供json包訪問。處理可選字段時(shí)使用指針或omitempty標(biāo)記以區(qū)分未提供與顯式零值。解析未知JSON時(shí)可採用map[string]interface{}並配合類型斷言提取數(shù)據(jù),默認(rèn)數(shù)字會(huì)被解析為float64。調(diào)試時(shí)可用json.MarshalIndent美化輸出,但生產(chǎn)環(huán)境應(yīng)避免多餘格式化。掌握這些技巧可提升代碼的健壯性與可

GO程序如何使用CGO與C代碼進(jìn)行交互?權(quán)衡是什麼? GO程序如何使用CGO與C代碼進(jìn)行交互?權(quán)衡是什麼? Jun 10, 2025 am 12:14 AM

Go程序確實(shí)可以通過Cgo與C代碼交互,它允許Go直接調(diào)用C函數(shù)。使用Cgo時(shí),只需導(dǎo)入偽包“C”並在導(dǎo)入行上方的註釋中嵌入C代碼即可,例如包含C函數(shù)定義並調(diào)用它們。此外,可通過指定鏈接標(biāo)誌如#cgoLDFLAGS鏈接外部C庫。然而,使用Cgo需要注意多個(gè)問題:1.內(nèi)存管理需手動(dòng)處理,不能依賴Go垃圾回收;2.Go類型與C類型可能不匹配,應(yīng)使用如C.int等類型保證一致性;3.多goroutine調(diào)用非線程安全C庫可能導(dǎo)致並發(fā)問題;4.調(diào)用C代碼存在性能開銷,應(yīng)減少跨語言邊界調(diào)用次數(shù)。 Cgo的缺

如何在不同的操作系統(tǒng)和體系結(jié)構(gòu)進(jìn)行跨編譯GO應(yīng)用程序? 如何在不同的操作系統(tǒng)和體系結(jié)構(gòu)進(jìn)行跨編譯GO應(yīng)用程序? Jun 11, 2025 am 12:12 AM

是的,goapplicationscanbecross-compiledfordfordferentoperatingsystemSandarchitures.todothis,firstSetthegoosandGoarchenVironMantVariaBlestVariablestoSpecifyThetArgetOsanchitector,sustasasAsAsGoos = linuxgoarch = linuxgoarch = amd64foralinuxbinarionorgoos = amd64foralinuxbinaryorgoos = windowsgoarchgoarch = arm64 forarkarcarch = arm644444444444444444444

Go如何處理指針,它們與C/C中的指針有何不同? Go如何處理指針,它們與C/C中的指針有何不同? Jun 10, 2025 am 12:13 AM

Go簡(jiǎn)化了指針的使用,提升了安全性。 1.不支持指針運(yùn)算,防止內(nèi)存錯(cuò)誤;2.自動(dòng)垃圾回收管理內(nèi)存,無需手動(dòng)分配或釋放;3.結(jié)構(gòu)體方法可無縫使用值或指針,語法更簡(jiǎn)潔;4.默認(rèn)安全指針,減少懸空指針和內(nèi)存洩漏風(fēng)險(xiǎn)。這些設(shè)計(jì)使Go比C/C 更易用且安全,但犧牲了部分底層控制能力。

默認(rèn)情況下,GO靜態(tài)鏈接的含義是什麼? 默認(rèn)情況下,GO靜態(tài)鏈接的含義是什麼? Jun 19, 2025 am 01:08 AM

Go默認(rèn)將程序編譯為獨(dú)立二進(jìn)製文件,主要原因是靜態(tài)鏈接。 1.部署更簡(jiǎn)單:無需額外安裝依賴庫,可直接跨Linux發(fā)行版運(yùn)行;2.二進(jìn)制體積更大:包含所有依賴導(dǎo)致文件尺寸增加,但可通過構(gòu)建標(biāo)誌或壓縮工具優(yōu)化;3.更高的可預(yù)測(cè)性與安全性:避免外部庫版本變化帶來的風(fēng)險(xiǎn),增強(qiáng)穩(wěn)定性;4.運(yùn)行靈活性受限:無法熱更新共享庫,需重新編譯部署以修復(fù)依賴漏洞。這些特性使Go適用於CLI工具、微服務(wù)等場(chǎng)景,但在存儲(chǔ)受限或依賴集中管理的環(huán)境中需權(quán)衡取捨。

在沒有C中的手動(dòng)內(nèi)存管理的情況下,如何確保內(nèi)存安全性? 在沒有C中的手動(dòng)內(nèi)存管理的情況下,如何確保內(nèi)存安全性? Jun 19, 2025 am 01:11 AM

Goensuresmemorysafetywithoutmanualmanagementthroughautomaticgarbagecollection,nopointerarithmetic,safeconcurrency,andruntimechecks.First,Go’sgarbagecollectorautomaticallyreclaimsunusedmemory,preventingleaksanddanglingpointers.Second,itdisallowspointe

如何在GO中創(chuàng)建緩衝頻道? (例如,make(chan int,10)) 如何在GO中創(chuàng)建緩衝頻道? (例如,make(chan int,10)) Jun 20, 2025 am 01:07 AM

在Go中創(chuàng)建緩衝通道只需在make函數(shù)中指定容量參數(shù)即可。緩衝通道允許發(fā)送操作在沒有接收者時(shí)暫存數(shù)據(jù),只要未超過指定容量,例如ch:=make(chanint,10)創(chuàng)建了一個(gè)可存儲(chǔ)最多10個(gè)整型值的緩衝通道;與無緩衝通道不同,發(fā)送數(shù)據(jù)時(shí)不會(huì)立即阻塞,而是將數(shù)據(jù)暫存於緩衝區(qū)中,直到被接收者取走;使用時(shí)需注意:1.容量設(shè)置應(yīng)合理以避免內(nèi)存浪費(fèi)或頻繁阻塞;2.需防止緩衝區(qū)無限堆積數(shù)據(jù)導(dǎo)致內(nèi)存問題;3.可用chanstruct{}類型傳遞信號(hào)以節(jié)省資源;常見場(chǎng)景包括控制並發(fā)數(shù)量、生產(chǎn)者-消費(fèi)者模型及異

如何使用GO進(jìn)行系統(tǒng)編程任務(wù)? 如何使用GO進(jìn)行系統(tǒng)編程任務(wù)? Jun 19, 2025 am 01:10 AM

Go是系統(tǒng)編程的理想選擇,因?yàn)樗Y(jié)合了C等編譯型語言的性能與現(xiàn)代語言的易用性和安全性。 1.文件與目錄操作方面,Go的os包支持創(chuàng)建、刪除、重命名及檢查文件和目錄是否存在,使用os.ReadFile可一行代碼讀取整個(gè)文件,適用於編寫備份腳本或日誌處理工具;2.進(jìn)程管理方面,通過os/exec包的exec.Command函數(shù)可執(zhí)行外部命令、捕獲輸出、設(shè)置環(huán)境變量、重定向輸入輸出流以及控制進(jìn)程生命週期,適合用於自動(dòng)化工具和部署腳本;3.網(wǎng)絡(luò)與並發(fā)方面,net包支持TCP/UDP編程、DNS查詢及原始套

See all articles