用Go構建命令行應用程序:彩虹貓

喜歡命令行應用程序嗎?也不要錯過 cowsay 教程! 我正在尋找一些終端應用程序來尋找靈感,結果我偶然發現了 lolcat。 原始碼在 https://github.com/busyloop/lolcat,並且已經有了一些Go的實現: https://github.com/cezarsa/glolcat https://github.com/latotty/lolcat https://github.com/lalyos/lolcat https://github.com/vbatts/gogololcat 看起來是一個完全沒有用的東西,所以讓我們來實現它! 首先,讓我們在屏幕上打印一些值,然後我們將為它們上色,然後我們將研究如何接受用戶輸入以作為管道工作。 我使用 https://github.com/enodata/faker 生成假的輸出。 go get -u github.com/enodata/faker 該程序輸出了一些短語: package main import ( "fmt" "strings" "github.com/enodata/faker" ) func main() { var phrases []string for i := 1; i < 3; i++ { phrases = append(phrases, faker.Hacker().Phrases()...) } fmt.Println(strings.Join(phrases[:], "; ")) } 不幸的是,這都是無聊的黑白。讓我們添加一些顏色。我們可以通過在 fmt.Printf 中插入一個逸出字符序列來實現這一點。這樣就可以以金色 #FFD700(RGB顏色碼:255,215,0)打印所有字符串: package main import ( "fmt" "strings" "github.com/enodata/faker" ) func main() { var phrases []string for i := 1; i < 3; i++ { phrases = append(phrases, faker....

用於從子文件夾中提供多個Node.js應用程序的簡單nginx反向代理

最近我在DigitalOcean上設置了一個VPS,以在同一域名下運行幾個不同的Node.js腳本。 現在,您無法使兩個不同的Node.js應用程序監聽同一個端口,因此必須使用反向代理。常用的方法是使用Nginx。 我將每個Node應用程序設置為在自己的子文件夾中運行,所以我需要編輯Nginx配置: sudo nano /etc/nginx/sites-available/default 配置文件原始內容如下: server { listen 80 default\_server; listen [::]:80 default\_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server\_name hellonode; location ^~ /assets/ { gzip\_static on; expires 12h; add\_header Cache-Control public; } location / { proxy\_http\_version 1.1; proxy\_cache\_bypass $http\_upgrade; proxy\_set\_header Upgrade $http\_upgrade; proxy\_set\_header Connection 'upgrade'; proxy\_set\_header Host $host; proxy\_set\_header X-Real-IP $remote\_addr; proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for; proxy\_set\_header X-Forwarded-Proto $scheme; proxy\_pass http://localhost:3000; } } 這個配置允許一個Node.js應用程序在端口3000上運行,並且是主要在/處提供服務的應用程序。 我希望在/myservice下運行一個應用程序,所以我創建了一個在端口3001上監聽的Node應用程序,並添加了以下配置: location /myservice { rewrite ^/myservice/(....

用於觸發 JavaScript 函數的連結

當你使用純 JavaScript 創建應用程序時,有時你會需要在用戶點擊連結時觸發一個函數。 你通常可以通過以下兩種方式來實現。 假設你要執行的函數叫做 handleClick(): function handleClick() { alert('被點擊了'); } 第一種方式是使用以下連結: <a href="#" onclick="handleClick()">點擊這裡</a> 第二種方式是使用以下連結: <a href="javascript:void(0)" onclick="handleClick()">點擊這裡</a> 這兩種方式的語法非常相似,唯一的區別在於 href 屬性的值。 第一種方式是 href="#",第二種方式是 href="javascript:void(0)"。 你可能也會看到這種語法 href="javascript:;",它與第二種方式等價。 那麼,這兩種方式的行為有什麼不同呢? 當用戶點擊 href="#" 的連結時,你必須確保從事件處理程序中返回 false,否則瀏覽器會自動滾動到頁面頂部: function handleClick() { alert('被點擊了'); return false; } 此外,即使你添加了這個返回語句,但如果 JavaScript 被禁用或由於某些原因無法執行,瀏覽器仍會自動滾動到頁面頂部。這是一件幾乎總是要避免的事情,因此我個人會選擇使用第二種形式 href="javascript:void(0)"。 無論使用哪種方式,如果 JavaScript 被禁用或 JavaScript 中出現錯誤且 JavaScript 執行停止,則不會調用 handleClick() 函數。 為了防止這種情況,你可以在 href 中使用一個真實的 URL 作為後備方案,這樣瀏覽器將使用 GET HTTP 方法將用戶移動到特定頁面,儘管這不總是可能或方便。 但這是一種最佳實踐,而最佳實踐並不總是方便的,但你必須在應用程序設計階段考慮到它們,因為你不能只為理想情況構建應用程序,而忽略一切可能出錯的情況。 如果出了點問題,用戶會責怪你和你的壞連結 🙂

全端獨立開發者

當我們想到軟體開發者時,我們會想像一個經常待在電腦前的人,專注於創建某種改變世界的應用程式,花整晚改善軟體程序的效能,整天修復錯誤,或試圖創建下一個機器學習演算法。 對於許多從事傳統職業的開發者來說,這可能是真實的。他們為大公司、初創公司、銀行或其他雇主工作。 我們中的一些人,包括我自己,正在經歷完全不同的職業生涯。 有時候我會在YouTube上觀看一個關於某個非常冷門的編程話題的會議演講,然後我就想,“這個人是從哪裡找到時間學習這些東西的”? 對我來說,一天根本沒有足夠的時間去觀看那個演講,更不用說要先發現所有那些東西。然後我提醒自己,我與眾不同,我是全端的。 在網頁開發中,全端指的是你既做前端又做後端。但在這裡,我給全端一個不同的意義。這個意義是我通過Thiago Forte的這篇文章發現的,而我是通過Mr RIP的這篇文章發現的。 我是一名獨立的軟體開發者。我從…讓我查查…從一開始就是獨立的。我從來沒有被任何人雇用過。我從來都不是僱員,是承包商,自由職業者,但從未是僱員。 回顧過去,我一直是一名兼職承包商。一半時間工作來支付生活費,另一半時間用來開發自己的獨立項目。網頁應用程式、手機應用程式、開源軟體、CMS插件、主題、桌面應用程式、培訓項目,我嘗試過一切。有時是愚蠢的想法,有時不是。 在作為受僱的軟體開發者工作時,你需要的技能與作為獨立軟體開發者時需要的技能之間存在著天壤之別。 想像一下,你想創建自己的軟體產品並獨立銷售。 你必須扮演很多角色! 你必須知道如何確保你所工作的項目是一個好主意。這並不是簡單的,還涉及運氣和時機。 你必須擅長品牌設計,為你的應用程式想出一個令人難忘的名字。 你必須是一個優秀的設計師,能夠設計好看的登陸頁面。 你必須是一位優秀的文案撰稿人,知道如何在這個登陸頁面上說些什麼。 你必須是一位網頁開發者,來創建登陸頁面。 你必須是一位運維專家,負責部署登陸頁面。 你必須擅長營銷。這是你知道如何收集首個測試版的電子郵件的方法。 你需要有一些法律條款。隱私、條款、GDPR… 我有什麼遺漏嗎?哦,是的,我們還沒開始為你想要銷售的軟體產品工作。 你必須很擅長這個。出色的執行能力、堅實的後端、可擴展的架構、優秀的UI和UX、安全性。 你需要知道如何部署應用程式,如何快速部署更新,如何避免在遷移中崩潰。 然後你需要擅長營銷。我希望你已經有了一個感興趣的目標群體,否則你會發現“建立了它們就會來”的不真實性。你需要知道如何撰寫被潛在客戶打開的電子郵件。 你需要學習如何搜尋引擎優化,如何進行內容營銷,如何銷售,在播客或YouTube頻道上作客以提高對你的產品的認知度。 我希望你是一個出色的演講者,最好是一個以英語為母語的人。 當然,你可以雇用某人來幫助你。我提到了大約15個不同的專業領域。其中一些需要至少五個人的團隊。 現在讓我們獲得一些風險投資金錢,每個月支付這些30-40人的薪水,希望你已經有了一些在矽谷的好聯繫! 除非你像我一樣是一個全端獨立開發者,並且你非常喜歡做這些事情。戴上你需要戴的所有帽子,讓你的創作落地並交到客戶手中。 而在99%的情況下,最終你會失敗,花時間閱讀Indie Hackers上的成功故事。 或者也許你會屬於那1%,並且獲得成功。

合併 Git 提交記錄

我每天都使用 Git,過去我曾寫過一篇 Git 指南 和一份 Git Cheat Sheet。 我自認為是一名 Git 的愛好者,但……我不是一個 Git 專家。 提交、抓取遠程庫、拉取遠程庫、推送到遠程庫……這是我每天使用 Git 的日常事務。 儘管如此,我還是會用一些 Git 的進階功能: Git 能做的進階操作讓我感到驚訝。它可以非常複雜,但我傾向於避免複雜的操作。我幾乎從不使用命令行工具進行 Git 操作,而是使用 GitHub Desktop,這是迄今為止最簡單和最好用的 Git 客戶端。 然而,有兩個功能我有時會使用,分別是 cherry-picking 和合併提交記錄。 讓我們來談談這兩個功能。 在只有我一個開發者的項目中(也就是所有我個人的項目),我往往傾向於直接在主分支(master)上進行工作。例如,如果我只是進行一個簡單的更改,或者向博客添加一篇新文章。這些都是快速且不會破壞原有功能的工作。 但在某些情況下,我並不使用這種方式,而是為一個大的功能創建一個分支。 這在團隊或者開源項目中也是默認的方式。 你創建一個分支,並且經常提交。早期和頻繁地提交有很大的優勢,因為你可以有信心地在代碼上進行工作,知道你總能回到一個正常的狀態,或者至少回到你知道某些東西是正常的之前的狀態。 你可能會進行一系列快速的提交,其中的提交信息可能是“ok”,“試驗這個”,或者“修復愚蠢的錯誤”。 但是在某個時候,你需要收斂到一個穩定的狀態,將更改提交回主分支(master)或任何你想合併的分支。 在那之前,你需要做一件事情:合併(squashing)你的提交記錄。 在 Github 中,當你合併一個 Pull Request 時,它可以自動為你合併提交記錄。這是我過去在公開的開源項目中使用得非常多的工作流程。你只會看到一個提交,而不是在 Pull Request 中包含的所有獨立提交。在 PR 合併過程中,你可以編寫詳細的提交訊息和說明。 這將消除所有與你要合併的分支的頭部(head)不一致的前一個 Git 提交記錄,也將刪除那些可能撤消更改的提交記錄等等。 這就是 Github PR 流程中的合併(squashing)。你也可以在 Github 之外進行合併(squashing)。 一旦你在一個分支上的工作完成,你將 master(或任何你想要合併的分支)合併進來: git merge master 這樣你可以解決任何更新衝突。 然後你切換到 master 分支,並運行以下命令: git merge --squash <你的功能分支> 然後執行...

向 Set 添加項目

# JavaScript 的 Set 數據結構 Set 數據結構允許將數據添加到容器中,這個容器可以是對象或基本類型(字符串、數字或布爾值)的集合,你可以將它看作是一個 Map,其中值被用作 Map 的鍵,而 Map 的值始終是一個布爾值 true。 什麼是 Set 初始化 Set 向 Set 添加項目 檢查 Set 中是否存在項目 按鍵刪除 Set 中的項目 確定 Set 中的項目數量 刪除 Set 中的所有項目 遍歷 Set 中的項目 使用值初始化 Set 轉換為數組 將 Set 的鍵轉換為數組 WeakSet 什麼是 Set Set 是一種數據結構,用於將數據添加到容器中。 ECMAScript 6(又稱 ES2015)引入了 Set 數據結構到 JavaScript 世界,並且帶有 Map 一起引入。 Set 是一個對象或基本類型(字符串、數字或布爾值)的集合,你可以將它看作是一個 Map,其中值被用作 Map 的鍵,而這個 Map 的值始終是一個布爾值 true。 初始化 Set 可以通過調用以下方法來初始化 Set: const s = new Set() 向 Set 添加項目 你可以使用 add 方法將項目添加到 Set 中:...

在 Astro 中構建可組合的布局

在建立網站時,我喜歡將所有的布局分散在不同的文件中。 假如我想建立一個登陸頁面。 我之前做的是一個純HTML的頁面。這非常好,沒有比這更簡單和更簡約的了。 但是後來我意識到我還想在網站上創建另一個類似的頁面,但具有相同的樣式和結構。 開始出現重複代碼的問題。然後我想要另一個頁面,最後我決定對所有頁面的標題進行更改,而這變得讓人沮喪。 這就是靜態網站生成器發揮作用的時候了。 在許多工具中,比如 Hugo,你可以使用 partials(局部文件)。 在 Astro 中,這全部基於組件,因此我們可以導入和嵌入 JSX 中的組件: --- import Header from ../components/Header.astro import Footer from ../components/Footer.astro --- <html> <body> <Header /> <h1>A page</h1> <Footer /> </body> </html> 然後我們可以在組件中複製/粘貼這個結構。 請注意,其中仍然有一些我們可以提取的 HTML 內容,以避免複製/粘貼代碼。 我們使用佈局來實現這一點。 您可以在 src/layouts 文件夾中創建佈局: --- import Header from ../components/Header.astro import Footer from ../components/Footer.astro --- <html> <body> <Header /> <slot /> <Footer /> </body> </html> 注意 <slot /> 的使用方式。 這是我們可以在其中嵌入任何來自其他組件的內容的方法。 我們可以這樣使用佈局: --- import MyLayout from '....

在 C 中如何找到字符串的長度

一個關於如何在 C 中找到字符串長度的實用教程 可以使用 C 標準函式庫 string.h 頭文件中提供的 strlen() 函數。 char name[7] = "Flavio"; strlen(name); 這個函數將返回字符串的長度作為一個整數值。 工作示例: #include <string.h> #include <stdio.h> int main(void) { char name[7] = "Flavio"; int length = strlen(name); printf("姓名長度: %u", length); }

在 C 中循環遍歷數組

如何在 C 中循環遍歷數組 數組的主要用途之一是與循環一起使用。 假設有一個這樣的數組: const int SIZE = 5; int prices[SIZE] = { 1, 2, 3, 4, 5 }; 你可以使用 for 循環遍歷每個元素,如下: for (int i = 0; i < SIZE; i++) { printf("%u\n", prices[i]); }

在 Docker 容器中部署 Go 應用程式

簡介 安裝 Go 官方鏡像 一個範例應用 將應用程式擺到 Docker 精簡 Docker 映像檔 多階段建置 簡介 如果你從沒聽過 Docker,不過這很不可能,第一件你應該知道的事情是 Docker 允許你以隔離方式執行應用程式,高度關注於分離的問題,但同時允許它們與外部世界通訊和互動。 還有你應該知道的是,每個人都在使用它,每個主要的雲端服務提供商也都有專用於運行容器的解決方案,所以你應該學習它! 安裝 安裝方法隨你的系統而異,所以請查看 https://www.docker.com/get-docker。 我假設你已經安裝了 Docker,並在你的 shell 中可以使用 docker 命令。 Go 官方鏡像 Docker 維護著許多不同語言的官方鏡像清單,Go 也不例外,它是 2014 年原始 官方鏡像推出 的一部分。 官方鏡像庫可以在這裡找到: https://hub.docker.com/_/golang/。有許多標籤可以識別所需的 Go 版本,以及想要提取的操作系統。 一個範例應用 作為範例,我將在 Docker 容器中部署一個小型的 Go 應用程式。它在 8000 port 監聽,以 q 作為查詢參數來獲得網頁,然後取回並印出找到的連結: package main import ( "fmt" "log" "net/http" "golang.org/x/net/html" ) func main() { http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe("0.0.0.0:8000", nil)) } func handler(w http....