Go程式語言中文教學網站

專業的Go程式語言繁體中文教學及練習範例網站,認識Go語言入門、Go語言工作、包含語法、iota、pointer、package、JSON、file I/O、HTTP server、REST API、goroutine、worker pool、generics等詳細Go程式語言教學。

20 完整章節主題
30+ Go 程式碼範例
互動 複製程式碼 / 範例輸出 / 進度儲存
進階 JSON、HTTP、REST、Worker Pool、Generics

課程總覽

本網站採用章節式導覽與範例驅動學習方式,從入門語法一路擴展到 Web 開發、並行處理與 generics。

1. 安裝與環境

建立專案、執行第一支 Go 程式。

2. 基礎語法

package、import、main、輸出與註解。

3. 型別系統

變數、零值、型別推斷與基本型別。

4. iota 與常數

列舉值、位元旗標與狀態定義。

5. Pointer

理解位址、解參考與傳址修改。

6. 流程控制

if、switch、for、range。

7. 函式與錯誤

多回傳值、error、defer。

8. Slice 與 Map

最常用容器資料結構。

9. Struct / Method / Interface

封裝資料與抽象行為。

10. Package / Module

拆分專案與重用程式碼。

11. JSON / File I/O

常見資料交換與檔案操作。

12. HTTP / REST / Worker Pool / Generics

面向實務的中高階主題。

安裝與 Hello World

從建立目錄、初始化 module 到執行第一支程式,是 Go 新手最標準的起點。

入門步驟

建立第一個專案

  1. 安裝 Go
  2. 建立資料夾 hello
  3. 執行 go mod init example/hello
  4. 建立 hello.go
  5. 執行 go run .
終端機命令

初始化專案

mkdir hello
cd hello
go mod init example/hello
go run .
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

Go 語法基礎

Go 程式通常由 package、import 與 main function 組成,語法簡潔、風格一致。

package

用於組織程式碼;執行程式常用 main 套件。

import

引入標準函式庫,例如 fmtosnet/http

註解

單行用 //,多行用 /* ... */

package main

import "fmt"

// main 是程式入口
func main() {
    fmt.Println("Go 語法學習開始!")
}
Go 習慣使用 gofmt 統一格式,這也是 Go 專案看起來一致、可讀性高的重要原因。

變數與型別

Go 支援明確型別與型別推斷,也有零值概念,這是後續理解資料結構與記憶體操作的基礎。

型別 範例 說明
int 10 整數
float64 3.14 浮點數
string "Hello" 字串
bool true / false 布林值
package main

import "fmt"

func main() {
    var age int = 18
    language := "Go"
    isFast := true

    fmt.Println(age)
    fmt.Println(language)
    fmt.Println(isFast)
}

重點整理

  • var name type = value:完整宣告
  • name := value:簡短宣告,只能在函式內使用
  • 未初始化變數會有零值
  • Go 重視明確型別與可預測行為

常數與 iota

Go 的常數可以是 typed 或 untyped,iota 常用來建立一組連續值,例如列舉、狀態碼或位元旗標。

重點觀念

  • 常數不可在執行期間被改變
  • Go 有 typed constants 與 untyped constants
  • iota 只在 const 宣告區塊中使用
  • 常見用途:狀態列舉、權限位元、流程代碼
package main

import "fmt"

const (
    Pending = iota
    Approved
    Rejected
)

func main() {
    fmt.Println(Pending)
    fmt.Println(Approved)
    fmt.Println(Rejected)
}
package main

import "fmt"

const (
    Read = 1 << iota
    Write
    Execute
)

func main() {
    fmt.Println(Read)
    fmt.Println(Write)
    fmt.Println(Execute)
}

Pointer 指標

Pointer 儲存變數位址,能讓函式直接修改原始資料。未初始化的 pointer 其值為 nil

package main

import "fmt"

func main() {
    x := 10
    p := &x

    fmt.Println(x)
    *p = 20
    fmt.Println(x)
}
package main

import "fmt"

func addFive(n *int) {
    *n += 5
}

func main() {
    score := 10
    addFive(&score)
    fmt.Println(score)
}
傳 pointer 給函式時,能避免複製大型資料,也可直接修改原值。

條件與迴圈

Go 沒有 while,主要使用 for;另外 ifswitch 可以帶初始化敘述。

package main

import "fmt"

func main() {
    score := 85

    if score >= 60 {
        fmt.Println("及格")
    } else {
        fmt.Println("不及格")
    }
}
package main

import "fmt"

func main() {
    for i := 0; i < 5; i++ {
        fmt.Println(i)
    }
}
range 是 Go 中遍歷 slice、map、array、string 的常用方式。

函式與錯誤處理

Go 的函式可回傳多個值,這讓錯誤處理模式清晰直接。defer 常用於資源釋放與收尾操作。

package main

import "fmt"

func add(a int, b int) int {
    return a + b
}

func main() {
    fmt.Println(add(5, 7))
}
package main

import "fmt"

func main() {
    defer fmt.Println("結束前執行 defer")
    fmt.Println("開始")
}
package main

import "fmt"

func divide(a, b int) (int, int) {
    return a / b, a % b
}

func main() {
    q, r := divide(10, 2)
    fmt.Println("商為:", q)
    fmt.Println("餘數:", r)
}

陣列 / Slice / Map

切片與映射是 Go 中最常用的資料容器之一,理解長度、容量、append 與 key/value 操作非常重要。

package main

import "fmt"

func main() {
    langs := []string{"Go", "Java"}
    langs = append(langs, "Python")

    fmt.Println(langs)
    fmt.Println(len(langs))
}
package main

import "fmt"

func main() {
    student := map[string]interface{}{
        "name": "Alice",
        "score": 95,
    }

    fmt.Println(student["name"])
    fmt.Println(student["score"])
}
make 常用來建立 slice、map、channel;而 newmake 的用途不同,是 Go 初學的重要觀念。

Struct / Method / Interface

Go 沒有傳統 class,但可以用 struct、method、interface 建構清楚且可維護的抽象設計。

package main

import "fmt"

type User struct {
    Name string
}

func (u User) Greet() string {
    return "Hi, 我是 " + u.Name
}

func main() {
    user := User{Name: "Gopher"}
    fmt.Println(user.Greet())
}
package main

import "fmt"

type Speaker interface {
    Speak() string
}

type Dog struct{}

func (d Dog) Speak() string {
    return "汪!"
}

func main() {
    var s Speaker = Dog{}
    fmt.Println(s.Speak())
}
Go 的 interface 是隱式實作,不需要顯式寫出 implements。

Package 拆分與模組

Go 程式碼以 package 組織,package 再被歸屬到 module 中。實務上會把功能拆成多個 package 來維持可讀性與可重用性。

範例目錄結構

myapp/
├─ go.mod
├─ main.go
└─ utils/
   └─ math.go
模組管理是 Go 專案維護與重用的重要基礎。

建立模組

go mod init example.com/myapp
// utils/math.go
package utils

func Add(a int, b int) int {
    return a + b
}
// main.go
package main

import (
    "fmt"
    "example.com/myapp/utils"
)

func main() {
    fmt.Println(utils.Add(3, 5))
}

JSON 處理

Go 標準套件 encoding/json 支援資料編碼與解碼,最重要的是 json.Marshaljson.Unmarshal 與 struct tag。

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    u := User{Name: "Alice", Age: 20}
    data, _ := json.Marshal(u)
    fmt.Println(string(data))
}
package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    text := `{"name":"Bob","age":25}`
    var u User
    json.Unmarshal([]byte(text), &u)

    fmt.Println(u.Name)
    fmt.Println(u.Age)
}
進一步可再擴充 omitemptyMarshalIndentDecoderEncoder 的教學。

File I/O 檔案操作

Go 初學最常用的是 os.ReadFileos.WriteFile,進一步才會學 os.Openos.CreateReadWriteClose

package main

import (
    "fmt"
    "os"
)

func main() {
    err := os.WriteFile("hello.txt", []byte("Hello Go File"), 0644)
    if err != nil {
        fmt.Println("寫入失敗:", err)
        return
    }
    fmt.Println("寫入完成")
}
package main

import (
    "fmt"
    "os"
)

func main() {
    data, err := os.ReadFile("hello.txt")
    if err != nil {
        fmt.Println("讀取失敗:", err)
        return
    }
    fmt.Println(string(data))
}
這一章很適合後續再加入「建立資料夾、刪除檔案、逐段讀寫」等範例。

HTTP Server

Go 的 net/http 是內建的 Web 開發基礎。最常見的入門方式是 http.HandleFunc 搭配 http.ListenAndServe

package main

import (
    "fmt"
    "net/http"
)

func home(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "歡迎來到 Go HTTP Server")
}

func main() {
    http.HandleFunc("/", home)
    fmt.Println("伺服器啟動於 http://localhost:8080")
    http.ListenAndServe(":8080", nil)
}
若要更進一步,可教自訂 router、middleware、timeout 與靜態檔案服務。

REST API 範例

REST API 教學可結合 net/httpencoding/json,示範回傳 JSON、解析請求與建立簡單資源列表。

package main

import (
    "encoding/json"
    "net/http"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

func usersHandler(w http.ResponseWriter, r *http.Request) {
    users := []User{
        {ID: 1, Name: "Alice"},
        {ID: 2, Name: "Bob"},
    }

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(users)
}

func main() {
    http.HandleFunc("/users", usersHandler)
    http.ListenAndServe(":8080", nil)
}

這章可再擴充

  • GET /users
  • GET /users/{id}
  • POST /users
  • PUT /users/{id}
  • DELETE /users/{id}

教學建議

這一章很適合加入 Postman 測試說明、status code、request body 解析、路由拆分與錯誤回應格式。

Goroutine / Channel

並行是 Go 的核心魅力之一。教學站應展示 goroutine、channel、同步思維與常見範例。

package main

import "fmt"

func main() {
    ch := make(chan string)

    go func() {
        ch <- "Hello from goroutine"
    }()

    msg := <-ch
    fmt.Println("收到訊息:", msg)
}
goroutine 的執行順序通常不保證固定,因此多執行緒輸出常會有順序差異。

Goroutine + Worker Pool

Worker Pool 是 Go 並行教學中的經典範例,能幫助使用者理解 jobs channel、results channel 與 goroutine 協作。

package main

import "fmt"

func worker(id int, jobs <-chan int, results chan<- int) {
    for job := range jobs {
        fmt.Println("worker", id, "處理工作", job)
        results <- job * 2
    }
}

func main() {
    jobs := make(chan int, 3)
    results := make(chan int, 3)

    go worker(1, jobs, results)
    go worker(2, jobs, results)

    jobs <- 1
    jobs <- 2
    jobs <- 3
    close(jobs)

    fmt.Println("結果:", <-results)
    fmt.Println("結果:", <-results)
    fmt.Println("結果:", <-results)
}
這類範例非常適合銜接 goroutine 與 channel 章節,幫助學生理解工作佇列與結果收集。

Generics 基礎

Go 的 generics 讓你可以為多種型別撰寫共用邏輯。核心概念包含 type parameters、constraints、comparable 與 type inference。

重點觀念

  • 使用方括號宣告 type parameters
  • constraint 限定可接受的型別
  • comparable 常用於 map key 或比對
  • Go 可在呼叫時自動做 type inference
package main

import "fmt"

type Number interface {
    int | float64
}

func Sum[T Number](a, b, c T) T {
    return a + b + c
}

func main() {
    fmt.Println(Sum(1, 2, 3))
    fmt.Println(Sum(1.5, 2.5, 3.5))
}