跳至主要內容

Poetry 備忘錄

· 3 分鐘閱讀

這篇備忘錄記錄了 Poetry。

資訊

Poetry 是一個用於 Python 項目依賴管理和打包的工具。它旨在提供一個更簡潔、更直觀的開發體驗,解決了傳統 Python 項目中 pipvirtualenv 的一些痛點。

Poetry 將依賴管理、虛擬環境、打包和發布功能集成到一個工具中,使得 Python 項目的生命週期管理更加順暢。

1. 安裝 Poetry

推薦使用官方提供的腳本進行安裝:

Linux / macOS / WSL

curl -sSL https://install.python-poetry.org | python3 -

Windows (PowerShell)

(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | python -

安裝完成後,你可能需要將 Poetry 的可執行路徑添加到你的 PATH 環境變量中。安裝腳本通常會給出提示。

2. 創建新專案

要創建一個新的 Poetry 專案:

poetry new my-project
cd my-project

這會創建一個包含以下結構的新目錄:

my-project/
├── my_project/
│ └── __init__.py
└── pyproject.toml
└── README.md

3. pyproject.toml 文件

Poetry 使用 pyproject.toml 文件來管理項目元數據和依賴。這是 Poetry 的核心配置文件。

範例 pyproject.toml

[tool.poetry]
name = "my-project"
version = "0.1.0"
description = ""
authors = ["Your Name <[email protected]>"]
readme = "README.md"
packages = [{include = "my_project"}] # 指定你的 Python 包

[tool.poetry.dependencies]
python = "^3.10" # 指定 Python 版本
requests = "^2.28.1" # 運行時依賴

[tool.poetry.group.dev.dependencies]
pytest = "^7.1.2" # 開發時依賴 (例如測試工具)

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

4. 管理依賴

添加依賴

poetry add requests    # 添加運行時依賴
poetry add --group dev pytest # 添加開發時依賴

這會更新 pyproject.toml 並安裝依賴到虛擬環境中。

移除依賴

poetry remove requests
poetry remove --group dev pytest

安裝依賴

如果 pyproject.tomlpoetry.lock 已經存在,安裝所有依賴:

poetry install

更新依賴

更新所有依賴到最新兼容版本:

poetry update

更新指定依賴:

poetry update requests

5. 虛擬環境

Poetry 會自動為每個專案創建和管理虛擬環境。

運行命令

在虛擬環境中運行命令:

poetry run python my_script.py

進入虛擬環境 Shell

poetry shell

然後你就可以直接運行 python 或其他已安裝的命令。

查看虛擬環境信息

poetry env info

刪除虛擬環境

poetry env remove python3.10 # 替換為實際的 Python 版本或環境路徑

6. 打包和發布

打包專案

創建一個源發行版(sdist)和一個輪子文件(wheel):

poetry build

打包文件會生成在 dist/ 目錄中。

發布到 PyPI

在發布之前,請確保你的 pyproject.toml 中的元數據是準確的。

poetry publish

如果你是第一次發布,可能需要配置 PyPI 憑據。

poetry config pypi-token.pypi <your-pypi-token>

7. 總結

Poetry 是一個現代化的 Python 項目管理工具,它簡化了依賴管理、虛擬環境、打包和發布的整個流程。它的 pyproject.toml 文件提供了一個清晰且中心化的方式來定義項目元數據和依賴,大大提升了開發效率和項目可維護性。

建立個人主頁

· 4 分鐘閱讀

這篇備忘錄記錄了如何建立個人主頁。

資訊

建立個人主頁是展示個人作品、技能、簡歷和聯絡方式的重要方式。它可以用作個人品牌建設、求職或僅僅作為一個分享興趣愛好的平台。

1. 選擇技術棧

建立個人主頁有許多種方法,從靜態網頁到複雜的內容管理系統 (CMS)。選擇合適的技術棧取決於你的需求和技術熟練度。

A. 靜態站點生成器 (SSG) - 推薦

靜態站點生成器是建立個人主頁的流行選擇,因為它們易於部署、加載速度快、安全且通常免費託管。

  • Docusaurus:用於建立文檔網站(如本網站)。它基於 React,支持 Markdown,並提供內置的搜尋、版本控制和國際化功能。
  • Jekyll:基於 Ruby 的 SSG,與 GitHub Pages 緊密集成。
  • Hugo:基於 Go 語言的 SSG,以其極快的構建速度而聞名。
  • Next.js / Gatsby:基於 React 的框架,可以生成靜態站點。

B. 前端框架 (SPA)

如果你需要更多互動性或動態內容,可以使用前端框架創建單頁應用程式 (SPA)。

  • React
  • Vue.js
  • Angular

C. 內容管理系統 (CMS)

如果你希望有管理界面來輕鬆更新內容,可以使用 CMS。

  • WordPress
  • Joomla
  • Ghost

2. 規劃內容

在開始編寫程式碼之前,先規劃你的主頁應該包含哪些內容。常見的內容區塊包括:

  • 首頁 / 關於我:簡要介紹自己、你的興趣和目標。
  • 作品集 / 專案:展示你的最佳作品,包括截圖、鏈接和簡要說明。
  • 技能:列出你的技術技能、程式語言、工具和框架。
  • 經歷 / 簡歷:你的教育背景、工作經歷和成就。
  • 部落格 / 文章:如果你喜歡寫作,可以分享你的知識和見解。
  • 聯絡方式:電子郵件、GitHub、LinkedIn、Twitter 等社交媒體鏈接。

3. 建立個人主頁 (以 Docusaurus 為例)

本網站就是使用 Docusaurus 建立的,所以這裡以 Docusaurus 為例。

A. 建立 Docusaurus 專案

npx create-docusaurus@latest my-website classic --typescript
cd my-website

B. 配置 Docusaurus

編輯 docusaurus.config.ts 文件以配置網站標題、導航欄、腳註等。

C. 建立個人主頁內容

  1. 修改首頁: 默認的首頁是 src/pages/index.tsx。你可以編輯這個 React 組件來設計你的首頁。

    // src/pages/index.tsx
    import React from 'react';
    import clsx from 'clsx';
    import Layout from '@theme/Layout';
    import Link from '@docusaurus/Link';
    import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
    import styles from './index.module.css';
    import HomepageFeatures from '../components/HomepageFeatures';

    function HomepageHeader() {
    const {siteConfig} = useDocusaurusContext();
    return (
    <header className={clsx('hero hero--primary', styles.heroBanner)}>
    <div className="container">
    <h1 className="hero__title">{siteConfig.title}</h1>
    <p className="hero__subtitle">{siteConfig.tagline}</p>
    <div className={styles.buttons}>
    <Link
    className="button button--secondary button--lg"
    to="/docs/intro">
    我的簡歷 - 5min 閱讀 ⏱️
    </Link>
    </div>
    </div>
    </header>
    );
    }

    export default function Home(): JSX.Element {
    const {siteConfig} = useDocusaurusContext();
    return (
    <Layout
    title={`Hello from ${siteConfig.title}`}
    description="Description will go into a meta tag in <head />">
    <HomepageHeader />
    <main>
    <HomepageFeatures />
    </main>
    </Layout>
    );
    }
  2. 建立個人資料頁面 (例如 about.md): 你可以在 docs/ 目錄下創建 Markdown 文件作為關於你的頁面。

    <!-- docs/about.md -->
    ---
    sidebar_position: 1
    ---

    # 關於我

    你好!我是 [你的名字],一位熱愛 [你的興趣] 的 [你的職位/角色]。
    我在 [領域] 擁有 [X] 年的經驗,專注於 [你的專長]。

    ## 我的技能

    - 程式語言:Python, JavaScript, C#
    - 框架:React, Node.js, .NET
    - 工具:Git, Docker, Kubernetes

    ## 我的專案

    - **專案 A**:[鏈接] - 簡要說明
    - **專案 B**:[鏈接] - 簡要說明

    ## 聯絡方式

    - 電子郵件:[email protected]
    - GitHub:[你的 GitHub]
    - LinkedIn:[你的 LinkedIn]
  3. 配置導航欄: 在 docusaurus.config.ts 中修改 navbar 配置,添加指向你的關於我頁面、部落格等鏈接。

    navbar: {
    title: 'Hikari Dev',
    logo: {
    alt: 'My Site Logo',
    src: 'img/logo.svg',
    },
    items: [
    {
    type: 'doc',
    docId: 'intro', // 指向你的關於我或簡歷文檔
    position: 'left',
    label: '關於我',
    },
    {to: '/blog', label: '部落格', position: 'left'},
    // ... 其他鏈接
    ],
    },

D. 部署網站

最簡單的方法是使用 GitHub Pages 或 Vercel / Netlify。Docusaurus 有內置的部署功能。

  • GitHub Pages: 在 docusaurus.config.ts 中配置 baseUrlprojectName
    baseUrl: '/<your-repo-name>/', // 例如,如果你的 repo 是 yourusername.github.io/my-website
    projectName: 'my-website',
    organizationName: 'yourusername',
    然後運行部署命令:
    GIT_USER=<YOUR_GITHUB_USERNAME> USE_SSH=true yarn deploy

總結

建立個人主頁是一個展現自己的絕佳機會。選擇合適的工具、精心策劃內容,並利用靜態站點生成器等現代技術,你可以輕鬆地建立一個專業且美觀的個人網站。

C# 中的 MD5 雜湊

· 3 分鐘閱讀

這篇備忘錄記錄了在 C# 中實現 MD5 雜湊的方法。

資訊

MD5 (Message-Digest Algorithm 5) 是一種廣泛使用的加密雜湊函數,它生成一個 128 位(16 字節)的雜湊值。儘管 MD5 在加密安全方面已被認為不再安全(存在碰撞攻擊),但它仍然經常用於文件完整性校驗或非安全數據的快速雜湊。

1. 使用 System.Security.Cryptography.MD5

C# 提供了內置的 MD5 類(位於 System.Security.Cryptography 命名空間)來計算 MD5 雜湊值。

範例:對字串進行 MD5 雜湊

using System;
using System.Security.Cryptography;
using System.Text;

public class Md5Hasher
{
public static string CalculateMd5Hash(string input)
{
// 創建 MD5 雜湊算法的實例
using (MD5 md5 = MD5.Create())
{
// 將輸入字串轉換為字節數組
byte[] inputBytes = Encoding.UTF8.GetBytes(input);

// 計算雜湊值
byte[] hashBytes = md5.ComputeHash(inputBytes);

// 將字節數組轉換為十六進制字串
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("x2")); // "x2" 格式化為兩位十六進制
}
return sb.ToString();
}
}

public static void Main(string[] args)
{
string text = "Hello, MD5!";
string hash = CalculateMd5Hash(text);
Console.WriteLine($"原始字串: {text}");
Console.WriteLine($"MD5 雜湊: {hash}");

// 預期的 MD5 雜湊值 for "Hello, MD5!" (小寫)
// 9e2469446d3288a7c207b04cfd6e01a4
}
}

範例:對文件進行 MD5 雜湊

對文件內容計算 MD5 雜湊通常用於驗證文件是否在傳輸過程中被修改。

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class FileMd5Hasher
{
public static string CalculateFileMd5Hash(string filePath)
{
if (!File.Exists(filePath))
{
return "文件不存在。";
}

using (MD5 md5 = MD5.Create())
{
using (FileStream stream = File.OpenRead(filePath))
{
byte[] hashBytes = md5.ComputeHash(stream);

StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("x2"));
}
return sb.ToString();
}
}
}

public static void Main(string[] args)
{
string filePath = "example.txt"; // 替換為你的文件路徑

// 創建一個範例文件
File.WriteAllText(filePath, "這是一個測試文件的內容。");

string fileHash = CalculateFileMd5Hash(filePath);
Console.WriteLine($"文件路徑: {filePath}");
Console.WriteLine($"文件 MD5 雜湊: {fileHash}");

// 清理範例文件
File.Delete(filePath);
}
}

2. 安全注意事項

  • 不適用於密碼儲存:由於 MD5 存在嚴重的安全漏洞(例如碰撞攻擊),絕對不應該將其用於儲存用戶密碼。對於密碼,應使用專為此目的設計的單向雜湊函數,如 PBKDF2、bcrypt 或 scrypt。
  • 不適用於數字簽名或認證:同樣,MD5 不應在需要強加密安全的場景中使用。
  • 用途:主要用途應該限於文件完整性校驗(驗證文件是否被意外更改)或生成非安全數據的快速雜湊。

總結

C# 中的 MD5 類提供了一種簡單直觀的方式來計算 MD5 雜湊值。雖然它在安全性方面存在限制,但在正確的應用場景下(如文件校驗),它仍然是一個有用的工具。務必牢記其安全限制,避免在加密敏感的上下文中使用它。

CUDA Grid 和 Block

· 4 分鐘閱讀

這篇備忘錄記錄了 CUDA Grid 和 Block。

資訊

在 CUDA 中,並行執行的程式碼稱為核函數 (Kernel)。當你啟動一個核函數時,你必須指定執行該核函數的線程數量以及它們如何組織。這就是 Grid (網格) 和 Block (塊) 的概念。

1. 線程層次結構

CUDA 的線程模型是一個分層結構:

  • Grid (網格):由一個或多個 Block 組成。Grid 可以是一維、二維或三維的。
  • Block (塊):由多個線程組成。Block 也可以是一維、二維或三維的。
  • Thread (線程):Grid 中執行的最小單位。每個線程都執行相同的核函數程式碼。

這種層次結構允許你將問題分解為獨立的子任務,並將這些子任務映射到 Grid 和 Block 的維度上。

2. 定義 Grid 和 Block 維度

在啟動核函數時,你使用 <<<Dg, Db>>> 語法來指定 Grid 和 Block 的維度:

kernel_function<<<Dg, Db>>>(arguments);
  • Dg (Dimension Grid):指定 Grid 的維度。這是一個 dim3 類型的變量,可以是一維 (Dg.x)、二維 (Dg.x, Dg.y) 或三維 (Dg.x, Dg.y, Dg.z)。
  • Db (Dimension Block):指定每個 Block 的維度。這也是一個 dim3 類型的變量,可以是一維 (Db.x)、二維 (Db.y) 或三維 (Db.z)。

dim3 結構體

dim3 是一個結構體,通常用於表示 Grid 或 Block 的大小。

struct dim3
{
unsigned int x, y, z;
};

如果你只指定一個值,它會被賦給 .x,其他為 1。例如 dim3(10) 等同於 dim3(10, 1, 1)

3. 線程索引

在核函數內部,每個線程都可以通過幾個內置變量來識別自己的唯一索引:

  • blockIdx.x, blockIdx.y, blockIdx.z:當前線程所在的 Block 在 Grid 中的索引。
  • blockDim.x, blockDim.y, blockDim.z:每個 Block 的維度(線程數)。
  • threadIdx.x, threadIdx.y, threadIdx.z:當前線程在 Block 中的索引。
  • gridDim.x, gridDim.y, gridDim.z:Grid 的維度(Block 數)。

通過這些變量,可以計算出每個線程在整個 Grid 中的全局唯一索引。

一維索引計算

對於一維 Grid 和 Block,全局索引的計算方式為:

int global_index = blockIdx.x * blockDim.x + threadIdx.x;

二維索引計算

對於二維 Grid 和 Block,全局索引的計算方式為:

int x_index = blockIdx.x * blockDim.x + threadIdx.x;
int y_index = blockIdx.y * blockDim.y + threadIdx.y;

// 如果將二維數據存儲在一維數組中,則需要將 (x_index, y_index) 轉換為一維索引
// 假設矩陣寬度為 width
int global_index = y_index * width + x_index;

範例:向量加法

這是一個簡單的向量加法核函數,演示了 Grid 和 Block 的使用。

#include <iostream>
#include <vector>
#include <cuda_runtime.h>

// 核函數:在設備上執行向量加法
__global__ void add_vectors(int* a, int* b, int* c, int N) {
// 計算當前線程在 Grid 中的全局索引
int idx = blockIdx.x * blockDim.x + threadIdx.x;

// 確保索引在有效範圍內
if (idx < N) {
c[idx] = a[idx] + b[idx];
}
}

int main() {
int N = 100000; // 向量大小
size_t size = N * sizeof(int);

// 主機 (CPU) 數據
std::vector<int> h_a(N), h_b(N), h_c(N);

// 初始化主機數據
for (int i = 0; i < N; ++i) {
h_a[i] = i;
h_b[i] = i * 2;
}

// 設備 (GPU) 數據指針
int *d_a, *d_b, *d_c;

// 在設備上分配內存
cudaMalloc((void**)&d_a, size);
cudaMalloc((void**)&d_b, size);
cudaMalloc((void**)&d_c, size);

// 將數據從主機複製到設備
cudaMemcpy(d_a, h_a.data(), size, cudaMemcpyHostToDevice);
cudaMemcpy(d_b, h_b.data(), size, cudaMemcpyHostToDevice);

// 配置 Grid 和 Block 維度
int threadsPerBlock = 256;
int blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock; // 確保覆蓋所有元素

// 啟動核函數
add_vectors<<<blocksPerGrid, threadsPerBlock>>>(d_a, d_b, d_c, N);

// 將結果從設備複製回主機
cudaMemcpy(h_c.data(), d_c, size, cudaMemcpyDeviceToHost);

// 驗證結果 (可選)
std::cout << "h_c[0] = " << h_c[0] << std::endl; // 0 + 0 = 0
std::cout << "h_c[1] = " << h_c[1] << std::endl; // 1 + 2 = 3
std::cout << "h_c[N-1] = " << h_c[N-1] << std::endl; // (N-1) + 2*(N-1) = 3*(N-1)

// 釋放設備內存
cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c);

return 0;
}

總結

理解 CUDA 的 Grid 和 Block 概念對於有效利用 GPU 的並行計算能力至關重要。通過合理地組織線程,你可以將複雜的計算任務分解為數百萬個小任務,並在 GPU 上高效地執行它們。

Rust 隨機數

· 3 分鐘閱讀

這篇備忘錄記錄了如何在 Rust 中生成隨機數。

資訊

Rust 的標準庫不直接包含生成隨機數的功能,而是通過 rand crate 提供。rand 是一個強大且靈活的庫,支持多種隨機數生成器和分佈。

1. 添加 rand 依賴

首先,你需要將 rand crate 添加到你的 Cargo.toml 文件中:

[dependencies]
rand = "0.8" # 使用 0.8.x 系列的最新版本

2. 生成隨機整數

使用 rand::Rng trait 來生成隨機數。最簡單的方法是使用 rand::thread_rng() 獲取一個線程局部隨機數生成器。

use rand::Rng; // 導入 Rng trait

fn main() {
let mut rng = rand::thread_rng(); // 獲取線程局部隨機數生成器

// 生成一個範圍在 [1, 10) 之間的隨機整數 (不包含 10)
let random_int = rng.gen_range(1..10);
println!("隨機整數 (1-9): {}", random_int);

// 生成一個範圍在 [1, 10] 之間的隨機整數 (包含 10)
let random_int_inclusive = rng.gen_range(1..=10);
println!("隨機整數 (1-10): {}", random_int_inclusive);

// 生成一個布爾值
let random_bool = rng.gen_bool(0.5); // 0.5 的概率為 true
println!("隨機布爾值: {}", random_bool);
}

3. 生成隨機浮點數

gen_range 也可以用於浮點數。

use rand::Rng;

fn main() {
let mut rng = rand::thread_rng();

// 生成一個範圍在 [0.0, 1.0) 之間的隨機浮點數 (不包含 1.0)
let random_float = rng.gen_range(0.0..1.0);
println!("隨機浮點數 (0.0-1.0): {}", random_float);

// 生成一個範圍在 [10.0, 20.0) 之間的隨機浮點數
let random_float_custom = rng.gen_range(10.0..20.0);
println!("隨機浮點數 (10.0-20.0): {}", random_float_custom);
}

4. 從列表中隨機選擇

你可以使用 rand::seq::SliceRandom trait 來從切片(如向量或數組)中隨機選擇元素或打亂順序。

use rand::seq::SliceRandom;
use rand::Rng;

fn main() {
let mut rng = rand::thread_rng();
let choices = ["蘋果", "香蕉", "櫻桃", "日期"];

// 隨機選擇一個元素
let random_choice = choices.choose(&mut rng);
println!("隨機選擇: {:?}", random_choice.unwrap());

// 隨機選擇多個元素 (可能重複)
let mut selected_multiple: Vec<&str> = (0..2)
.map(|_| choices.choose(&mut rng).unwrap())
.collect();
println!("隨機選擇多個: {:?}", selected_multiple);

// 隨機打亂向量的順序
let mut numbers = vec![1, 2, 3, 4, 5];
numbers.shuffle(&mut rng);
println!("打亂後的數字: {:?}", numbers);
}

5. 自定義隨機數生成器 (PRNG)

如果你需要可重複的隨機數序列,或者需要不同的隨機數生成器,你可以使用 rand crate 提供的各種 PRNG。例如,StdRng 是一個確定性隨機數生成器。

[dependencies]
rand = { version = "0.8", features = ["std"] } # 確保啟用 "std" feature 以使用 StdRng
rand_chacha = "0.3" # 引入一個具體的 PRNG 實現
use rand::{SeedableRng, Rng};
use rand_chacha::ChaCha8Rng; // 使用 ChaCha8Rng 作為範例

fn main() {
// 使用固定的種子創建一個隨機數生成器
let seed = [0; 32]; // 32 字節的種子
let mut rng = ChaCha8Rng::from_seed(seed);

let random_value1 = rng.gen_range(0..100);
println!("第一個隨機值: {}", random_value1);

let random_value2 = rng.gen_range(0..100);
println!("第二個隨機值: {}", random_value2);

// 如果再次使用相同的種子,將會得到相同的序列
let mut another_rng = ChaCha8Rng::from_seed(seed);
let another_value1 = another_rng.gen_range(0..100);
println!("再次使用相同種子得到的值: {}", another_value1);
}

總結

rand crate 為 Rust 提供了全面且安全的隨機數生成功能。無論是簡單的隨機數,從集合中選擇,還是需要自定義隨機數生成器,rand 都能滿足你的需求。記得在 Cargo.toml 中添加正確的依賴。

PC 環境備忘錄

· 3 分鐘閱讀

這篇備忘錄記錄了個人電腦 (PC) 環境設置的一些常用配置和工具。

1. 作業系統

Windows

  • Windows Subsystem for Linux (WSL):在 Windows 上運行 Linux 環境的最佳方式。推薦安裝 WSL2。
  • PowerShell:Windows 的強大命令行 Shell。
    • Oh My Posh:自定義 PowerShell 提示符,使其更美觀和功能豐富。
  • 包管理器 (Package Manager)
    • Winget:Windows 內置的應用程式包管理器。
    • Chocolatey:另一個流行的 Windows 包管理器。

Linux (Ubuntu/Debian)

  • 桌面環境:GNOME (默認), KDE Plasma, XFCE 等。
  • 終端模擬器
    • GNOME Terminal (默認)
    • Tilix:平鋪式終端模擬器,支持多個面板。
    • Alacritty:GPU 加速的終端模擬器,速度快。
  • Shell
    • Bash (默認)
    • Zsh + Oh My Zsh:高度可自定義,提供豐富的插件和主題。
  • 包管理器apt (Debian/Ubuntu)。

macOS

  • iTerm2:功能豐富的終端模擬器,比默認的 Terminal 更好用。
  • Homebrew:macOS 的包管理器,大大簡化了軟體安裝。
  • Zsh + Oh My Zsh (默認 Shell)。

2. 開發工具

文本編輯器 / IDE

  • Visual Studio Code (VS Code):輕量級但功能強大的程式碼編輯器,支持大量擴展。
  • JetBrains IDEs:如 IntelliJ IDEA (Java), PyCharm (Python), WebStorm (Web) 等,功能齊全的專業 IDE。
  • Vim / NeoVim:高效的命令行文本編輯器,學習曲線陡峭但效率極高。
  • Emacs:另一個強大的可自定義編輯器。

版本控制

  • Git:分布式版本控制系統,幾乎是所有開發者的必備工具。
    • GUI 工具:GitKraken, SourceTree, VS Code 內置 Git 支持。

程式語言運行環境

  • Node.js:JavaScript 運行時。
    • NVM (Node Version Manager):管理多個 Node.js 版本。
  • Python
    • pyenv:管理多個 Python 版本。
    • Poetry / pipenv:虛擬環境和依賴管理工具。
  • Ruby
    • rbenv / RVM:管理多個 Ruby 版本。
  • Go
  • Rust

容器化

  • Docker:容器化平台,用於打包和運行應用程式。
  • Kubernetes (K8s):容器編排系統。

3. 實用工具

  • 文件同步
    • OneDrive / Google Drive / Dropbox:雲端同步。
    • Syncthing:開源的點對點文件同步工具。
  • 密碼管理器
    • Bitwarden:開源、跨平台。
    • LastPass
  • 截圖工具
    • ShareX (Windows):功能豐富。
    • Flameshot (Linux):
  • VPN:保護網絡隱私。
  • 剪貼板管理器
    • Ditto (Windows)
    • Gnome Clipboard Indicator (Linux)
  • 搜索工具
    • Everything (Windows):極速文件搜索。
    • fzf (Linux/macOS):模糊查找器。

4. 網絡配置

  • DNS 設定:更改為公共 DNS (如 8.8.8.8, 1.1.1.1) 以提高解析速度和隱私。
  • SSH 密鑰:用於安全地連接到遠端服務器。

總結

建立一個高效且舒適的 PC 環境是一個持續的過程,它涉及到選擇適合你工作流程的工具和配置。這篇備忘錄提供了一個起點,你可以根據自己的需求進一步探索和客製化。

IT 護照英文縮寫整理

· 4 分鐘閱讀
縮寫全名意義
CSRCorporate Social Responsibility企業以合乎道德、永續且對社會負責的方式營運的責任。
SDGsSustainable Development Goals聯合國通過的17項全球目標,旨在推動永續發展。
OJTOn the Job Training員工在工作崗位上進行的在職訓練。
Off-JTOff the Job Training員工離開工作崗位進行的訓練。
HRTechHuman Resource Technology將資訊技術應用於人力資源管理。
CEOChief Executive Officer公司最高層的經營者,負責整體組織的成功。
CIOChief Information Officer負責運用資訊技術達成組織目標的高階主管。
COOChief Operating Officer負責企業日常行政與營運功能的高階主管。
CFOChief Financial Officer負責管理公司財務風險的高階主管。
ABC 分析依重要性將資料分為三類的柏拉圖分析法。
B/SBalance Sheet顯示公司在特定時間點的資產、負債與股東權益的財務報表。
ROEReturn On Equity衡量公司相對於股東權益盈利能力的比率。
JAN CodeJapanese Article Number日本使用的條碼標準。
QR CodeQuick Response能儲存比傳統條碼更多資料的二維條碼。
ISOInternational Organization for Standardization制定與發布國際標準的國際組織。
SWOT 分析Strengths・Weaknesses・Opportunities・Threats用於評估公司優勢、劣勢、機會與威脅的策略規劃工具。
PPMProduct Portfolio Management將產品分類為明星、金牛、問題兒童與落水狗的管理方法。
M&AMergers and Acquisitions兩家或多家公司合併為一家的行為。
VCVenture Capital投資高成長潛力新創企業的投資公司。
IPOInitial Public Offering私人公司首次向公眾發行股票。
TOBTake Over Bid公司直接向股東購買股份以收購另一家公司的要約收購。
MBOManagement Buyout公司管理團隊購買公司股票的交易。
4PProduct・Price・Place・Promotion行銷的四個P:產品、價格、通路與促銷。
4CCustomer Value・Cost・Convenience・Communication以買方為中心的行銷組合方式。
RFM 分析Recency・Frequency・Monetary依最近購買時間、購買頻率與購買金額分析顧客購買行為。
UXUser Experience使用者在使用產品、系統或服務時的體驗。
BSCBalance Scorecard從財務、顧客、內部流程及學習成長四個面向衡量公司績效的策略管理工具。
CSFCritical Success Factors對公司成功至關重要的因素。
KPIKey Performance Indicator衡量公司是否有效達成關鍵業務目標的量化指標。
ERPEnterprise Resource Planning整合企業財務、人力資源及供應鏈管理等各面向的系統。
CRMCustomer Relationship Management管理公司與現有及潛在顧客互動關係的系統。
SFASales Force Automation自動化銷售任務並提升銷售團隊效率的軟體。
SCMSupply Chain Management管理從原料到最終消費者的商品與服務流動。
RFIDRadio Frequency Identification利用無線電波識別與追蹤物體的技術。
NFCNear Field Communication近距離無線通訊技術。
AIArtificial Intelligence開發能執行通常需要人類智慧任務的電腦系統。
POS SystemPoint of Sale處理銷售交易的系統。
CADComputer Aided Design使用電腦軟體設計產品。
CAMComputer Aided Manufacturing使用電腦軟體控制製造流程。
JITJust In Time僅在需要時才生產商品以將庫存降至最低的製造策略。
ECElectronic Commerce透過網際網路進行商品與服務的買賣。
IoTInternet of Things嵌入感測器、軟體及其他技術以連接並與其他裝置及系統交換資料的實體物體網絡。
Society 5.0融合實體與虛擬世界以實現經濟發展並解決社會問題的社會形態。
EAEnterprise Architecture設計與實施組織資訊系統的框架。
SoESystem of Engagement強化與顧客關係的系統。
DFDData Flow Design顯示資料如何在系統中流動的圖表。

Git 備忘錄

· 3 分鐘閱讀

這篇備忘錄記錄了 Git 的一些常用命令和概念。

資訊

Git 是一個免費開源的分布式版本控制系統 (Distributed Version Control System, DVCS),旨在以速度和效率處理從小到大的所有項目。它允許開發人員跟踪其程式碼庫中的更改,協作開發,並在需要時回溯到早期版本。

1. 基本操作

初始化倉庫

在當前目錄中創建一個新的 Git 倉庫:

git init

克隆倉庫

克隆一個遠端倉庫到本地:

git clone <repository_url>

範例:

git clone https://github.com/git/git.git

添加文件到暫存區

將文件添加到暫存區(準備提交):

git add <file_name>      # 添加單個文件
git add . # 添加所有更改過的文件
git add -u # 添加所有已追蹤但已修改/刪除的文件(不包括新文件)
git add -A # 添加所有更改過的文件(包括新文件、修改和刪除)

提交更改

將暫存區中的更改提交到本地倉庫:

git commit -m "提交信息"

檢查狀態

查看工作目錄和暫存區的狀態:

git status

查看更改

查看工作目錄和暫存區之間的差異:

git diff                 # 查看未暫存的更改
git diff --staged # 查看已暫存但未提交的更改
git diff HEAD # 查看工作目錄與最新提交的差異

2. 分支操作

列出分支

列出本地分支:

git branch

列出所有分支(包括遠端分支):

git branch -a

創建分支

創建一個新分支:

git branch <new_branch_name>

切換分支

切換到指定分支:

git checkout <branch_name>

創建並切換到新分支:

git checkout -b <new_branch_name>

合併分支

將一個分支的更改合併到當前分支:

git merge <branch_to_merge>

刪除分支

刪除本地分支(需要先切換到其他分支):

git branch -d <branch_name>      # 刪除已合併的分支
git branch -D <branch_name> # 強制刪除未合併的分支

3. 遠端倉庫操作

查看遠端倉庫

查看配置的遠端倉庫:

git remote -v

添加遠端倉庫

添加一個遠端倉庫:

git remote add <remote_name> <repository_url>

範例:

git remote add origin https://github.com/yourusername/your_repo.git

推送更改

將本地分支的更改推送到遠端倉庫:

git push <remote_name> <branch_name>

範例:

git push origin main

拉取更改

從遠端倉庫拉取更改到本地分支:

git pull <remote_name> <branch_name>

範例:

git pull origin main

4. 歷史記錄

查看提交歷史

查看提交歷史:

git log
git log --oneline # 簡潔顯示
git log --graph --oneline --decorate # 圖形化顯示分支合併

回溯更改

  • 撤銷最新提交 (不保留更改)
    git reset --hard HEAD~1
  • 撤銷最新提交 (保留更改在工作目錄)
    git reset HEAD~1
  • 撤銷特定文件在特定提交中的更改
    git checkout <commit_hash> <file_path>

Revert 提交

創建一個新的提交來撤銷指定提交的更改,保留歷史記錄:

git revert <commit_hash>

5. 標籤 (Tags)

列出標籤

git tag

創建標籤

git tag -a v1.0 -m "版本 1.0"

推送標籤

git push origin --tags

總結

Git 是一個功能強大的版本控制系統,掌握這些基本命令可以讓你有效地管理程式碼、協同工作並應對各種開發場景。這篇備忘錄只涵蓋了 Git 的一部分功能,還有更多進階功能(如 rebase, cherry-pick, submodule 等)等待探索。

JavaScript 備忘錄

· 4 分鐘閱讀

這篇備忘錄記錄了 JavaScript。

資訊

JavaScript 是一種高階、解釋型、多範式的程式語言。它最常用於網頁瀏覽器,為網頁添加互動性,但隨著 Node.js 的出現,它也已成為服務器端開發的重要語言。

1. 變量宣告

JavaScript 有三種主要方式宣告變量:varletconst

  • var

    • 函數作用域 (Function-scoped)。
    • 存在變量提升 (Hoisting),但只提升宣告,不提升賦值。
    • 可以重複宣告和重新賦值。
    var x = 10;
    function func() {
    var y = 20;
    }
    console.log(x); // 10
    // console.log(y); // ReferenceError
  • let

    • 塊級作用域 (Block-scoped)。
    • 存在變量提升,但處於「暫時性死區」(Temporal Dead Zone, TDZ)。
    • 不能重複宣告,但可以重新賦值。
    let x = 10;
    if (true) {
    let y = 20;
    }
    console.log(x); // 10
    // console.log(y); // ReferenceError
  • const

    • 塊級作用域。
    • 存在變量提升,處於 TDZ。
    • 不能重複宣告,也不能重新賦值(對於原始類型)。對於物件和陣列,可以修改其內部屬性,但不能重新賦值整個變量。
    const x = 10;
    // x = 20; // TypeError: Assignment to constant variable.

    const obj = { a: 1 };
    obj.a = 2; // 允許
    // obj = { b: 3 }; // TypeError

2. 數據類型

JavaScript 有八種數據類型:

  • 原始類型 (Primitives)

    • String:文本數據 ("hello", 'world')
    • Number:數字 (整數或浮點數) (10, 3.14)
    • Boolean:布爾值 (true, false)
    • Null:表示空值或不存在的值 (null)
    • Undefined:表示未定義的值(變量已宣告但未賦值) (undefined)
    • Symbol (ES6):唯一且不可變的值。
    • BigInt (ES2020):表示大於 2^53 - 1 的整數。
  • 物件類型 (Object)

    • Object:所有其他數據類型的基礎。
      • 包括普通物件 ({ key: value })
      • 陣列 ([1, 2, 3])
      • 函數 (function() {})
      • 日期 (new Date())
      • 正則表達式 (/abc/)

3. 運算符

比較運算符

  • ==:寬鬆相等(會進行類型轉換)
  • ===:嚴格相等(不進行類型轉換)
  • !=:寬鬆不相等
  • !==:嚴格不相等
  • >, <, >=, <=

邏輯運算符

  • &&:邏輯與
  • ||:邏輯或
  • !:邏輯非

其他運算符

  • 算術運算符+, -, *, /, %, ** (冪運算)
  • 賦值運算符=, +=, -=, *=
  • 條件 (三元) 運算符condition ? expr1 : expr2
  • 展開運算符 (Spread operator) (...):用於展開可迭代對象。
    const arr1 = [1, 2];
    const arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4]
    const obj1 = { a: 1, b: 2 };
    const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
  • 其餘參數 (Rest parameters) (...):用於收集函數參數。
    function sum(a, b, ...rest) {
    console.log(rest); // 收集除了 a 和 b 之外的所有參數
    return a + b + rest.reduce((acc, val) => acc + val, 0);
    }
    sum(1, 2, 3, 4); // rest = [3, 4]

4. 函數

函數宣告

function greet(name) {
return `Hello, ${name}!`;
}

函數表達式

const greet = function(name) {
return `Hello, ${name}!`;
};

箭頭函數 (Arrow Functions, ES6)

  • 更簡潔的語法。
  • 沒有自己的 thisargumentssupernew.target。它們從父作用域繼承 this
  • 不能用作構造函數。
const greet = (name) => `Hello, ${name}!`;

// 多行語句
const add = (a, b) => {
const result = a + b;
return result;
};

5. 模塊 (ES Modules, ES6)

使用 importexport 關鍵字來組織程式碼。

導出 (Export)

// math.js
export const add = (a, b) => a + b;
export function subtract(a, b) {
return a - b;
}
export default class Calculator { /* ... */ }

導入 (Import)

// app.js
import { add, subtract } from './math.js';
import Calculator from './math.js';

console.log(add(5, 3));
const calc = new Calculator();

總結

JavaScript 是一個功能強大且不斷發展的語言。從變量宣告到函數和模塊,掌握這些基本概念是成為一名熟練的 JavaScript 開發者的基礎。隨著 ES6+ 的發展,許多新的特性和語法糖也極大地提高了開發效率。

如何安裝 Docker

· 3 分鐘閱讀

這篇備忘錄記錄了如何在 Linux(Ubuntu/Debian)上安裝 Docker。

資訊

Docker 是一個開源平台,用於開發、交付和運行應用程式。它允許你將應用程式及其所有依賴項打包到一個稱為容器的標準化單元中,該容器可以在任何地方運行。

1. 卸載舊版本 (如果存在)

如果你之前安裝過舊版本的 Docker,建議先將其卸載,以避免潛在的衝突。

sudo apt-get remove docker docker-engine docker.io containerd runc

2. 更新套件索引並安裝必要工具

更新 apt 套件索引,並安裝一些允許 apt 通過 HTTPS 使用儲存庫的必要工具:

sudo apt-get update
sudo apt-get install
ca-certificates
curl
gnupg
lsb-release

3. 添加 Docker 的官方 GPG 密鑰

為了驗證 Docker 套件的真實性,你需要添加 Docker 的官方 GPG 密鑰:

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

4. 設置儲存庫

添加 Docker 儲存庫到你的 apt 源列表:

echo 
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
資訊

$(lsb_release -cs) 會輸出你的 Ubuntu 代號,例如 focal (20.04) 或 jammy (22.04)。

5. 安裝 Docker Engine

再次更新 apt 套件索引,然後安裝 Docker Engine、Containerd 和 Docker Compose。

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

6. 驗證 Docker 安裝

通過運行 hello-world 影像來驗證 Docker Engine 是否正確安裝:

sudo docker run hello-world

如果一切正常,你會看到一條消息,表明 Docker 安裝成功。

7. 管理 Docker 作為非 root 用戶 (可選但推薦)

默認情況下,docker 命令需要 sudo 權限。如果你想作為非 root 用戶運行 Docker 命令,你需要將你的用戶添加到 docker 群組。

  1. 創建 docker 群組 (如果不存在):
    sudo groupadd docker
  2. 將當前用戶添加到 docker 群組
    sudo usermod -aG docker $USER
  3. 重新登錄: 為了使群組更改生效,你需要註銷並重新登錄,或者重啟你的系統。 或者,你可以運行 newgrp docker 命令,但這只會影響當前會話。

完成後,你可以無需 sudo 即可運行 Docker 命令:

docker run hello-world

8. 配置 Docker 在啟動時自動運行 (可選)

Docker 通常會自動配置為在系統啟動時運行。你可以檢查其狀態:

sudo systemctl status docker

如果它沒有在啟動時啟用,你可以手動啟用:

sudo systemctl enable docker.service
sudo systemctl enable containerd.service

總結

通過上述步驟,你可以在 Ubuntu/Debian 系統上成功安裝 Docker Engine 和相關工具。這將使你能夠開始使用容器來打包、部署和運行你的應用程式。記住將你的用戶添加到 docker 群組以獲得更方便的體驗。