# 🚀 轉職工程師零基礎學習指南: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>`: 強制退回到指定版本(之後的紀錄會消失,請謹慎使用)。

---
## 📄 忽略檔案 (.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)$ 快。

* **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):** 學習自動化程式碼從提交、測試到部署上線的整個流程,實現快速、可靠的功能交付。