iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0

截至目前為止,我們都把程式碼全部塞在 ./cmd/olivine/main.go 裡--雖然 AI 常常這麼幹,但這顯然不是個好主意。

App 結構體

我一般會習慣在 main package 底下建立一個 App{} 結構體,它會用來控制整個應用程式的生命週期(初始化、啟動、關閉等)。

首先,建立一個 App{},並且定義 main.(*App).Run() 用於啟動服務:

// file: ./cmd/olivine/app.go
package main

type App struct{}

func (*App) Run() error {}

遷移 TCP Server

將原本放在 ./cmd/olivine/main.go 的實作整個搬到 main.(*App).Run() 中。

// file: ./cmd/olivine/app.go

func (*App) Run() error {
	slog.Info("starting olivine server...")
	listener, err := net.Listen("tcp", ":16879")
	if err != nil {
		return fmt.Errorf("failed to listen tcp: %w", err)
	}
	defer listener.Close()

	for {
		connection, err := listener.Accept()
		if err != nil {
			slog.Error("failed to accept connection:", slog.Any("error", err))
			continue
		}
		go handleConnection(connection)
	}
}


func handleConnection(conn net.Conn) {
	defer conn.Close()

	reader := bufio.NewReader(conn)
	message, err := reader.ReadString('\n')
	if err != nil {
		slog.Error("failed to read from conn:", slog.Any("error", err))
		return
	}

	ackmsg := strings.ToUpper(strings.ToUpper(message))
	response := "ACK: " + ackmsg
	if _, err := conn.Write([]byte(response)); err != nil {
		slog.Error("failed to write to conn:", slog.Any("error", err))
		return
	}
}

並且在 main.go 調用 main.(*App).Run() 即可

// file: ./cmd/olivine/main.go
package main

import "log/slog"

func main() {
	app := &App{}
	if err := app.Run(); err != nil {
		slog.Error("failed to run app:", slog.Any("error", err))
	}
}

上一篇
[Day 04] TCP Server
系列文
從零開始打造 Redis:以 Go 建立 Production Ready 應用程式5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言