# 🚀 轉職工程師零基礎學習指南:Go (Golang) 與開發基礎 [TOC] --- ## 🎯 第一章:Go 程式設計基礎 本章節將為你打下最基本的程式邏輯和語法基礎。Go 是一門靜態強型別、編譯型的語言。 ### 1.1 變數 (Variables) 🧱 * **觀念:** 變數就像是你貼上標籤的「**儲存箱**」,用來在程式執行過程中暫時存放資料。 #### 變數命名慣例 (Naming Conventions) 在 Go 中,命名首字母的大小寫決定了該變數是否能被其他套件存取(Public/Private)。 | 慣例名稱 | 說明 | Go 使用情境 | 範例 | | :--- | :--- | :--- | :--- | | **Camel Case (小駝峰)** | 第一個單字首字母小寫。 | **Go 推薦**用於內部私有的變數與函式。 | `userAge`, `calculateTotal` | | **Pascal Case (大駝峰)** | 每個單字的首字母都大寫。 | **Go 規定**用於公開導出的變數與類別。 | `UserAccount`, `HttpRequest` | | **Snake Case (蛇型命名)** | 以底線連接。 | **Go 社群不建議**使用底線命名變數。 | `user_age` | #### 變數宣告 | 特性 | `var` 關鍵字 | `:=` 短變數宣告 | | :--- | :--- | :--- | | **適用範圍** | 可用於 **函式內** 與 **函式外** (Package 層級) | **僅限函式內部** | | **初始值** | 非必填(不填則給予該型別的「零值」) | **必填**(須靠初始值推導型別) | | **型別指定** | 可明確指定型別,也可由系統推導 | 只能由系統自動推導 | | **語法範例** | `var x int = 10` 或 `var y = "Hi"` | `z := 20.5` | --- #### 💡 快速判斷準則: 1. **全域變數**:一律使用 `var`。 2. **區域變數**:優先使用 `:=` 以保持代碼簡潔。 3. **只宣告不賦值**:使用 `var`(例如:`var user User`)。 #### 字串處理 1. strings.Contains(dessert, "豪華") //判斷一個字串裡「有沒有包含」另一個字串,回傳值是 bool 1. strings.HasPrefix("豪華蛋糕", "豪華") // 是否以某字開頭 1. strings.HasSuffix("蛋糕.jpg", ".jpg") // 是否以某字結尾 1. strings.ToUpper("cake") // 轉大寫 1. strings.Split("a,b,c", ",") // 切割 1. strings.Join([]string{"a","b"}, "-") // 組合 1. strings.TrimSpace(" cake ") // 去空白 * **Go 範例:** ```go package main import "fmt" func main() { // 方式 A:明確宣告型別 var age int = 25 // 方式 B:簡短宣告 (自動推導型別) name := "新手工程師" // 改變變數的值 age = age + 1 fmt.Printf("%s 的年齡是: %d\n", name, age) // 輸出:新手工程師 的年齡是: 26 } //input package main import "fmt" func main() { var name string fmt.Println("請輸入你的名字:") fmt.Scanln(&name) fmt.Printf("你好,%s!準備好開始練習了嗎?\n", name) } ``` 第一個出現的 %s 會對應到後面的第一個變數 name。 第二個出現的 %d 會對應到後面的第二個變數 age。 最後的 \n 確保印完這行後,游標會跳到下一行,不會跟後面的輸出擠在一起。 | 佔位符 | 用途 | 範例 | | ---- | ------ | -------- | | `%d` | 整數 | `10` | | `%s` | 字串 | `"Go"` | | `%f` | 浮點數 | `3.14` | | `%t` | 布林 | `true` | | `%v` | 自動判斷型別 | **新手救星** | x := 3.14159 fmt.Printf("%.1f\n", x) // 3.1 fmt.Printf("%.2f\n", x) // 3.14 fmt.Printf("%.3f\n", x) // 3.142 | 符號 | 意思 | | ---- | -------- | | `\n` | 換行 | | `\t` | Tab(空格) | | `\"` | 字串內的 `"` | | `\\` | 顯示 `\` | Printf 要換行 → 自己加 \n --- ### 1.2 資料型別 (Data Types) 🔢 * **觀念:** Go 是強型別語言,宣告後型別不可變更。 * **Go 範例:** ```go count := 10 // int pi := 3.14 // float64 greeting := "Hello Go" // string isLearning := true // bool fmt.Printf("%T\n", count) fmt.Printf("%T\n", isLearning) ``` --- ### 1.3 流程控制 (Flow Control) 🚦 * **觀念:** 讓程式根據條件決定執行哪一段程式碼。Go 的 if 不需要圓括號。 * **Go 範例 (if/else if/else):** ```go score := 75 if score >= 90 { fmt.Println("A 等級") } else if score >= 60 { fmt.Println("B 等級") } else { fmt.Println("C 等級") } ``` --- ### 1.4 迴圈 (Loops) 🔄 * **觀念:** Go 只有 for 一種迴圈,但功能非常強大。 * **Go 範例:** ``` for 初始值; 條件; 每次做什麼 { } ``` ```go // 標準計數 for i := 0; i < 5; i++ { fmt.Println("目前數字:", i) } // 走訪切片 (Slice) fruits := []string{"蘋果", "香蕉", "橘子"} for index, fruit := range fruits { fmt.Printf("索引 %d: %s\n", index, fruit) } // 計算總合 sum := 0 for i :=1; i <=100; i++{ sum=sum+i } fmt.Println("總和是:",sum) } ``` --- ### 1.5 函式 (Functions) ⚙️ * **觀念:** Go 函式支援多個回傳值,通常最後一個回傳值用於傳回錯誤。 * **Go 範例:** ```go func add(a int, b int) int { return a + b } func main() { result := add(3,5) fmt.Println("結果:",result) } ------ func getUserInfo() (string, int) { return "小明", 30 } ------ func main() { total := add(10, 5) name, age := getUserInfo() fmt.Printf("%s 今年 %d 歲\n", name, age) } ``` --- ### 1.6 序列與集合 (Slices, Maps) 🧺 #### ➡️ 切片 (Slices):有序、可變動 (Mutable) * **觀念:** 類似 Python 的 List,是 Go 最常用的集合型別。 ```go tasks := []string{"學習 Go", "撰寫履歷"} tasks = append(tasks, "面試") fmt.Println(tasks[0]) ----- 宣告一個 slice:[]int{10, 20, 30, 40} 用 for 把每個數字印出來 再印出所有數字的總和 func main() { numbers := []int{10, 20, 30, 40} sum := 0 for _, v := range numbers { fmt.Println("數字:", v) sum += v } fmt.Println("總和:", sum) } ``` #### ➡️ 映射 (Maps):鍵值對 (Key-Value) * **觀念:** 類似 Python 的 Dictionary。 ```go 1.建立與讀取 Map 目標:學會宣告、初始化、讀取 person := map[string]int{ "小明": 30, "小華": 25, } fmt.Println("年齡:", person["小明"]) ``` map[keyType]valueType 來宣告。 用 map[key] 讀取值。 value, ok := map[key] ok 是布林值,表示該key對應的值是否存在。 map[key] = value 更新值。 delete(map, key) 刪除元素。 ```go 2.判斷 Key 是否存在 目標:學會 value, ok := map[key] age, ok := person["小華"] if ok { fmt.Println("小華存在,年齡:", age) } else { fmt.Println("小華不存在") } ``` ```go 3.修改與刪除資料 目標:更新值、刪除 key // 修改值 person["小明"] = 31 fmt.Println("小明的新年齡:", person["小明"]) // 刪除 key delete(person, "小華") fmt.Println("刪除小華後的 Map:", person) ``` ```go 4.使用 for range 走訪 Map 目標:遍歷所有資料 for name, age := range person { fmt.Println(name, "的年齡是", age) } ``` for key, value := range map 遍歷所有資料。 注意 Map 遍歷順序是 不固定的。 ```go 5.計算總和與平均 目標:搭配 map 做簡單邏輯 sum := 0 for _, age := range person { sum += age } avg := float64(sum) / float64(len(person)) fmt.Println("總年齡:", sum) fmt.Println("平均年齡:", avg) ``` _ 代表忽略 key。 可以做簡單統計或邏輯運算。 ```go 6.統計字母出現次數 目標:Map 最常見用途 text := "hello golang" count := make(map[rune]int) // 使用 rune 來支援單字母 for _, ch := range text { if ch != ' ' { // 忽略空格 count[ch]++ } } fmt.Println("字母統計結果:") for ch, n := range count { fmt.Printf("%c: %d\n", ch, n) } ``` Map 最常用來做計數統計。 使用 rune 來處理單個字符。 --- #### 1.7 錯誤處理 (Error Handling) ⚠️ (進階補充) * **觀念:** Go 不使用 `try-catch`,而是將錯誤視為「值」。除了基礎回傳,實務上常搭配 `errors` 標準庫進行判斷。 #### 1. 哨兵錯誤 (Sentinel Errors) 預先定義特定的錯誤變數,方便在程式各處進行比對,這是 Go 最常見的模式。 ```go import ( "errors" "fmt" ) var ErrDataNotFound = errors.New("找不到資料") func search(id int) error { ///將錯誤視為function的回傳值 if id != 101 { return ErrDataNotFound } return nil } func main() { err := search(1) ///呼叫此function時 需用一個變數去接function的回傳值 if errors.Is(err, ErrDataNotFound) { fmt.Println("請重新檢查 ID 內容") } } ``` ```go //函式導向 (Function-Based) func StartExercise(weight int, eq Equipment) error //呼叫 if err := StartExercise(120, benchPress); err != nil { ... } 寫法: 這是一個獨立的「工具函式」。 為什麼這樣寫: * 外部檢查: 這種寫法通常用於「第三方檢查」或是「多物件操作」。 低耦合: 函式本身不屬於器材(Equipment),也不屬於人。它像是一個裁判,把「重量」跟「器材」丟進去,由它來判定合不合格。 適用場景: 當邏輯涉及多個不同的 Struct,或者是一個通用的驗證工具時。 //方法導向 (Method-Based) func (gc GymClass) CheckStatus(currentPeople int) error //呼叫 if err := yoga.CheckStatus(3); err != nil { ... } 寫法: 這是附屬於 GymClass 結構體的「方法(Method)」。 為什麼這樣寫: 封裝(Encapsulation): 這是物件導向的思維。課程「是否能開課」是課程自己的資訊(它知道自己的最低人數 MinParticipants),所以應該由課程自己來回答。 直覺性: 在 main 裡面呼叫時,寫成 yoga.CheckStatus(3) 非常直覺,就像在問這堂瑜珈課:「喂,你現在人數夠嗎?」 適用場景: 當邏輯高度依賴該物件內部的資料(如 gc.MinParticipants)時。 ``` #### 2. 延遲執行與恢復 (Defer, Panic, Recover) 當發生嚴重不可逆的錯誤時會觸發 `panic`。我們可以使用 `defer` 搭配 `recover` 來攔截,避免程式直接崩潰。 * panic 是一個內建函數,它代表的是「程式發生了不可恢復的嚴重錯誤」。這與一般的 error 不同,error 是預期內的錯誤(例如檔案找不到),而 panic 通常是預期外的災難。 * **觀念:** `defer` 會將其後方的函數調用,延遲到「包含它的函數即將回傳(Return)」之前才執行。它最常用於資源釋放,確保無論程式中途發生什麼事,該做的事一定會做。 ```go func protect() { defer func() { if r := recover(); r != nil { fmt.Printf("系統已從錯誤中恢復: %v\n", r) } }() fmt.Println("開始執行...") panic("發生嚴重意外!") // 手動觸發崩潰 } ``` --- ### 1.8 指標 (Pointers) 📍 * **觀念:** 指標儲存的是變數在記憶體中的 **位址 (Memory Address)**。Go 預設是「傳值 (Pass by Value)」,若想在函數內修改外部變數,就必須傳遞指標。 #### 1. 基礎操作符 * `&`:**取址**。取得變數所在的記憶體位址。 * `*`:**取值 (解引用)**。透過位址找到原本的資料。 ```go x := 10 ptr := &x // ptr 現在指向 x 的位址 fmt.Println(ptr) // 輸出位址 (如 0xc0000140a8) fmt.Println(*ptr) // 輸出 10 (取值) *ptr = 20 // 透過指標修改 x 的值 fmt.Println(x) // x 變成了 20 ``` #### 2. 傳值 vs. 傳指標 如果不傳指標,函數內部的修改將不會影響到外部原始變數。 ```go func updateByValue(n int) { //這邊傳入的參數可視為原本n的複製品 n = 100 // 僅修改複製品 } func updateByPointer(n *int) { *n = 100 // 直接修改該記憶體位址的值 } func main() { num := 10 updateByValue(num) fmt.Println(num) // 還是 10 updateByPointer(&num) fmt.Println(num) // 變成 100 } ``` ##### 2.1 深入探討:Pass by Value vs. Pass by Reference(重要 面試必考) 在程式語言理論中,這兩者的底層行為有顯著差異。雖然 Go 嚴格來說只有 Pass by Value,但我們通常會用指標來模擬 Pass by Reference。 | 特性 | 傳值 (Pass by Value) | 傳指標 (模擬 Pass by Reference) | | :--- | :--- | :--- | | **行為** | 複製一份完整的數據交給函數。 | 複製一份「記憶體位址」交給函數。 | | **記憶體** | 佔用更多空間(若資料很大)。 | 佔用空間小(僅一個位址的大小)。 | | **影響** | 函數內的修改不會影響原始變數。 | 函數內透過位址修改,會影響原始變數。 | | **安全** | 較安全,數據不會被意外改動。 | 需謹慎,多人操作同一位址可能出錯。 | #### 為什麼說 Go 只有 Pass by Value? 這是一個常見的誤解。當你把指標傳入函數時,Go 其實是**複製了那個「位址」**傳進去。 * **傳值:** 複製「整顆蘋果」給對方,對方咬一口,你的蘋果還在。 * **傳指標:** 複製「蘋果所在的位置地圖」給對方,對方順著地圖去咬一口,你的蘋果就缺了一塊。 #### 範例:記憶體視角 ```go func change(val int, ptr *int) { val = 99 // val 是 local 變數,有自己的記憶體空間 *ptr = 99 // ptr 儲存的是位址,*ptr 是指去該位址改掉原本的值 } func main() { a, b := 1, 1 change(a, &b) // a 依然是 1:因為傳進去的是 a 的複製品 // b 變成了 99:因為傳進去的是 b 的位址複製品,兩者指向同一個 b } ``` > ⚠️ **注意:Slice 和 Map 的陷阱** > 在 Go 中,Slice、Map 和 Channel 看起來像是 Pass by Reference(改了會影響外部),但它們本質上是**包含指標的結構體**。所以傳遞它們時,依然是傳值(複製了裡面的指標),這導致了「看起來像傳參照」的行為。 --- #### 3. 指標的零值 (nil) 當一個指標沒有指向任何地址時,它的值是 `nil`。 ```go var p *int if p == nil { fmt.Println("此指標目前為空 (nil)") } ``` > **什麼時候該用指標?** > 1. **修改狀態:** 需要在函數中改變傳入參數的值。 > 2. **效能:** 傳遞大型結構 (Struct) 時,傳地址比複製整個資料結構快。 > 3. **表示空值:** 用 `nil` 來代表「資料不存在」或「尚未初始化」。 --- ## 💻 第二章:工程師的核心工具與知識 ### 2.1 資料庫語言:SQL (Structured Query Language) 💾 * **觀念:** **SQL** 是專門用來**管理和操作關聯式資料庫**的語言。在 PostgreSQL 中,資料以「資料表 (Table)」的形式儲存,每張表由行 (Row) 與列 (Column) 組成。 **基本結構執行順序** ```SQL --SELECT 選取 --FROM 來源 SELECT * FROM students; ----- SELECT 姓名, 班級, 成績 FROM students; ``` ```SQL --WHERE 條件 SELECT 姓名, 班級, 成績 FROM students WHERE 姓名 LIKE '張%'('張_'); (%零個或多個任意字元 _一個字元) ----- 1. WHERE 成績 >= 80 AND 成績 < 90; 2. WHERE 成績 BETWEEN 80 AND 90; 3. WHERE 成績 BETWEEN 80 AND 90 AND 班級 = '1年1班'; ----- OR符合任一條件(AND語法優先層級比OR高) WHERE 成績 BETWEEN 80 AND 90 AND 班級 = '1年1班' OR 班級 = '1年2班'; (會出現1年2班低於高於分數的都會出現) 改成加圓括弧 1. WHERE 成績 BETWEEN 80 AND 90 AND (班級 = '1年1班' OR 班級 = '1年2班'); 2. WHERE 成績 BETWEEN 80 AND 90 AND (班級 IN ('1年1班', '1年2班')) ``` ```SQL --GROUP BY 將資料進行分組 --HAVING 篩選已分組的資料 --ORDER BY 順序 排序 ASC:小 → 大(預設) DESC:大 → 小 WHERE 班級 <> '1年2班' ORDER BY 班級, 成績 DSEC; ``` ```SQL ---LIMIT 筆數限制 SELECT 姓名, 班級, 成績 FROM students LIMIT 5; (查看接來五筆 使用OFFSET跳過指定筆數) SELECT 姓名, 班級, 成績 FROM students LIMIT 5 OFFSET 5; ``` | 函數 | 功能 | | --------- | ---- | | `COUNT()` | 計算筆數 | | `SUM()` | 加總 | | `AVG()` | 平均值 | | `MAX()` | 最大值 | | `MIN()` | 最小值 | | `ROUND` | 四捨五入 | #### 1. 建立資料表 (CREATE TABLE) 在操作資料前,我們必須先定義資料的結構。 ```SQL CREATE TABLE users ( id SERIAL PRIMARY KEY, -- 自動遞增的主鍵 name TEXT NOT NULL, -- 不可為空的文字 email VARCHAR(100) UNIQUE, -- 唯一且長度受限的字串 age INT, -- 整數 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 預設為目前時間 ); ``` #### 2. 新增資料 (INSERT) - Create 將新資料存入資料表中。 ```SQL -- 新增單筆資料 INSERT INTO users (name, email, age) VALUES ('Gemini', 'gemini@example.com', 25); -- 新增多筆資料 INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@test.com', 30), ('Bob', 'bob@test.com', 22); ``` #### 3. 查詢資料 (SELECT) - Read 從資料表中取出想要的資料。 ```SQL -- 查詢所有欄位 SELECT * FROM users; -- 查詢特定欄位並篩選條件 SELECT name, email FROM users WHERE age >= 25 ORDER BY age DESC; -- 依照年齡由大到小排序 ``` #### 4. 修改資料 (UPDATE) - Update 更新現有的資料內容。**注意:務必搭配 WHERE,否則會更新整張表!** ```SQL UPDATE users SET age = 26, name = 'Gemini Pro' WHERE id = 1; ``` #### 5. 刪除資料 (DELETE) - Delete 移除不再需要的資料。**注意:務必搭配 WHERE!** ```SQL DELETE FROM users WHERE email = 'bob@test.com'; -- 若要清空整張表但保留結構 -- TRUNCATE TABLE users; ``` --- ### 2.2 網際網路基礎知識 🌐 * **HTTP (HyperText Transfer Protocol):** 網頁瀏覽器和伺服器之間傳輸資料的**主要協定**。 * **HTTPS (HTTP Secure):** 在 HTTP 基礎上加入了 **SSL/TLS 加密層**,確保資料傳輸的安全性。 * **Domain (網域) 和 IP 位址:** **IP 位址**是設備的實際地址;**網域**是為了方便記憶而設計的名稱(例如 `google.com`)。 ### 2.3 版本控制:Git 與平台 (GitHub/GitLab) 🌲 # Git 基礎與進階常用指令筆記 * **觀念:** **Git** 是一個分散式版本控制系統,用來**追蹤程式碼的變更歷史**,讓協同開發變得有條不紊。 * **教學資源:** [PAPAYA 電腦教室 - Git/GitHub 快速上手](https://www.youtube.com/watch?v=FKXRiAiQFiY) --- ## 📸 Git 工作流程圖解 在使用指令前,理解 Git 的四個核心區域: 1. **工作區 (Working Directory)**:你實際編輯檔案的地方。 2. **暫存區 (Staging Area)**:準備要提交的檔案存放處(攝影棚)。 3. **本地儲存庫 (Local Repository)**:儲存版本紀錄的地方(你的電腦)。 4. **遠端儲存庫 (Remote Repository)**:雲端共享平台(如 GitHub)。 --- ## 🛠️ 核心與常用指令 ### 1. 建立與取得 * `git init`: 在當前資料夾建立一個新的 Git 儲存庫。 * `git clone <URL>`: 複製遠端的儲存庫到本地。 ### 2. 提交變更 (日常最常用) * `git status`: 檢查目前檔案狀態(哪些已修改、哪些在暫存區)。 * `git add <檔案>`: 將檔案加入**暫存區**(準備拍照)。 * `git add .` 代表加入全部變更。 * `git commit -m "訊息"`: 建立一個新的**版本紀錄**(按下快門)。 ### 3. 查看歷史與比較 * `git log --oneline`: 以簡潔的一行格式列出版本歷史。 * `git diff`: 比對工作區與暫存區之間的內容差異。 ### 4. 分支與協作 (Teamwork) * `git branch`: 查看目前所有分支。 * `git checkout -b <分支名>`: 建立並切換到新分支(開啟遊戲新進度線)。 * `git merge <分支名>`: 將指定分支的內容合併回目前分支。 ### 5. 與遠端同步 * `git push`: 將本地的變更上傳到遠端伺服庫。 * `git pull`: 從遠端下載最新變更並**自動合併**到本地。 * `git fetch`: 從遠端下載最新變更資訊,但**不自動合併**(較安全)。 ### 6. 撤銷與還原 (後悔藥) * `git checkout <檔案>`: 放棄目前的修改,還原成上個版本的狀態。 * `git reset --hard <版本ID>`: 強制退回到指定版本(之後的紀錄會消失,請謹慎使用)。 ![image](https://hackmd.io/_uploads/HkAD60fXZl.png) --- ## 📄 忽略檔案 (.gitignore) 在專案根目錄建立 `.gitignore` 檔案,寫入不希望被 Git 追蹤的檔案(如密碼檔、大型暫存檔),可保持儲存庫乾淨並保護隱私。 ### 2.4 API 知識:RESTful 風格 📲 * **觀念:** **API (Application Programming Interface)** 定義了兩個軟體系統如何互相溝通。 * **RESTful API:** 一種最流行的網頁 API 設計風格,它使用標準的 HTTP 方法對資源進行操作: * `GET`: **獲取**(查詢)。 * `POST`: **新增**(創建)。 * `PUT`/`PATCH`: **修改**(更新)。 * `DELETE`: **刪除**。 ## 🧠 第三章:工程師的內功心法:資料結構/演算法與作業系統基礎 ### 3.1 資料結構 (Data Structures, DS) 📦 #### (1) 堆疊 (Stack) * **觀念:** 遵循 **LIFO (Last-In, First-Out)** 原則。 * **Go 範例:** 用 `slice` 的 `append` (Push) 搭配索引與截取實現 Pop。 ```go package main import "fmt" func main() { stack := []string{} // Push stack = append(stack, "A") // Pop (取最後一個並移除) n := len(stack) - 1 latestData := stack[n] stack = stack[:n] fmt.Println(latestData) // 輸出:A } ``` #### (2) 佇列 (Queue) * **觀念:** 遵循 **FIFO (First-In, First-Out)** 原則。 * **Go 範例:** 用 `slice` 的 `append` (Enqueue) 搭配索引與截取實現 Dequeue。 ```go package main import "fmt" func main() { queue := []string{"任務 1"} // Enqueue queue = append(queue, "任務 2") // Dequeue (取第一個並移除) firstTask := queue[0] queue = queue[1:] fmt.Println(firstTask) // 輸出:任務 1 } ``` --- ### 3.2 演算法 (Algorithms) ⚙️ * **觀念:** 演算法是為了解決特定問題所設計的**明確步驟或指令集**。 * **時間複雜度 (Time Complexity):** 衡量演算法效率的指標,用 **Big O 符號** ($O()$) 表示。 * **重點:** 你需要追求更低的複雜度,例如 $O(1)$(最快)比 $O(n)$ 快。 ![image](https://hackmd.io/_uploads/Sk6cr8lzZx.png) * **Go 範例:** ```go package main import ( "fmt" "sort" ) func main() { numbers := []int{5, 2, 8, 1} // 使用 sort 套件內建的高效能排序演算法 sort.Ints(numbers) fmt.Println(numbers) // 輸出:[1 2 5 8] } ``` ---- ### 3.3 作業系統基本概念 (Operating System, OS) 🖥️ * **觀念:** 作業系統是電腦的**總管家**,它管理硬體資源(CPU、記憶體、硬碟)。 #### (1) 記憶體管理 (Memory Management) * 作業系統負責分配和回收電腦的**主記憶體 (RAM)** 給正在運行的程式。 #### (2) 行程與執行緒 (Processes and Threads) * **行程 (Process):** 一個**正在執行中的應用程式**,擁有自己的記憶體空間。 * **執行緒 (Thread):** 行程內的**最小執行單元**,多個執行緒可以**共享**行程的記憶體空間,常用於實現多工。 ---- ## 🗺️ 第四章:進階工程師職涯發展路線 (Roadmap) 學完上述基礎後,你已經具備了作為一個初級開發人員的知識。接著,你需要專注於提升開發流程的品質和效率。 1. **單元測試 (Unit Testing) & 整合測試 (Integration Testing):** 學習為程式碼撰寫自動化測試,確保程式品質,避免引入錯誤。 2. **Docker (容器化):** 學習使用 Docker 將你的應用程式及其所有依賴項**打包**在一個標準化的「容器」中,解決環境不一致的問題。 3. **Kubernetes (K8s) (容器編排):** 學習使用 K8s **自動化部署、擴展和管理**數百個 Docker 容器,是處理大規模應用的利器。 4. **CI/CD (持續整合/持續部署 - Continuous Integration/Continuous Deployment):** 學習自動化程式碼從提交、測試到部署上線的整個流程,實現快速、可靠的功能交付。