Skip to main content Skills Marktplatz Entdecken und erkunden Sie KI-Skills, die von der Community erstellt wurden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Prompt kopierenPrompt-Details anzeigen Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
npx skills add https://github.com/xu-xiang/everything-claude-code-zh --skill golang-patternsDer Befehl bleibt in einer Zeile. Scrollen Sie horizontal, um ihn vor dem Kopieren vollständig zu prüfen.
Sie bevorzugen eine lokale Kopie? Laden Sie die Dateien herunter, die SkillsMP derzeit vorliegen.
ZIP herunterladen Herunterladen... Mehr aus diesem Repository Verwandte Berufe SOC
Basierend auf der SOC-Berufsklassifikation
name golang-patterns description Idiomatic Go patterns, best practices, and conventions for building robust, efficient, and maintainable Go applications.
Go 開發模式
用於建構穩健、高效且可維護應用程式的慣用 Go 模式和最佳實務。
何時啟用
撰寫新的 Go 程式碼
審查 Go 程式碼
重構現有 Go 程式碼
設計 Go 套件/模組
核心原則
1. 簡單與清晰
Go 偏好簡單而非聰明。程式碼應該明顯且易讀。
func GetUser (id string ) (*User, error ) {
user, err := db.FindUser(id)
if err != nil {
return nil , fmt.Errorf("get user %s: %w" , id, err)
}
return user, nil
}
func GetUser (id string ) (*User, error ) {
return func () (*User, error ) {
if u, e := db.FindUser(id); e == nil {
return u, nil
} else {
, e
}
}()
}
return
nil
2. 讓零值有用
type Counter struct {
mu sync.Mutex
count int
}
func (c *Counter) Inc() {
c.mu.Lock()
c.count++
c.mu.Unlock()
}
var buf bytes.Buffer
buf.WriteString("hello" )
type BadCounter struct {
counts map [string ]int
}
3. 接受介面,回傳結構
func ProcessData (r io.Reader) (*Result, error ) {
data, err := io.ReadAll(r)
if err != nil {
return nil , err
}
return &Result{Data: data}, nil
}
func ProcessData (r io.Reader) (io.Reader, error ) {
}
錯誤處理模式
帶上下文的錯誤包裝
func LoadConfig (path string ) (*Config, error ) {
data, err := os.ReadFile(path)
if err != nil {
return nil , fmt.Errorf("load config %s: %w" , path, err)
}
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
return nil , fmt.Errorf("parse config %s: %w" , path, err)
}
return &cfg, nil
}
自訂錯誤類型
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation failed on %s: %s" , e.Field, e.Message)
}
var (
ErrNotFound = errors.New("resource not found" )
ErrUnauthorized = errors.New("unauthorized" )
ErrInvalidInput = errors.New("invalid input" )
)
使用 errors.Is 和 errors.As 檢查錯誤 func HandleError (err error ) {
if errors.Is(err, sql.ErrNoRows) {
log.Println("No records found" )
return
}
var validationErr *ValidationError
if errors.As(err, &validationErr) {
log.Printf("Validation error on field %s: %s" ,
validationErr.Field, validationErr.Message)
return
}
log.Printf("Unexpected error: %v" , err)
}
絕不忽略錯誤
result, _ := doSomething()
result, err := doSomething()
if err != nil {
return err
}
_ = writer.Close()
並行模式
Worker Pool func WorkerPool (jobs <-chan Job, results chan <- Result, numWorkers int ) {
var wg sync.WaitGroup
for i := 0 ; i < numWorkers; i++ {
wg.Add(1 )
go func () {
defer wg.Done()
for job := range jobs {
results <- process(job)
}
}()
}
wg.Wait()
close (results)
}
取消和逾時的 Context func FetchWithTimeout (ctx context.Context, url string ) ([]byte , error ) {
ctx, cancel := context.WithTimeout(ctx, 5 *time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET" , url, nil )
if err != nil {
return nil , fmt.Errorf("create request: %w" , err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil , fmt.Errorf("fetch %s: %w" , url, err)
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
優雅關閉 func GracefulShutdown (server *http.Server) {
quit := make (chan os.Signal, 1 )
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Shutting down server..." )
ctx, cancel := context.WithTimeout(context.Background(), 30 *time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Server forced to shutdown: %v" , err)
}
log.Println("Server exited" )
}
協調 Goroutines 的 errgroup import "golang.org/x/sync/errgroup"
func FetchAll (ctx context.Context, urls []string ) ([][]byte , error ) {
g, ctx := errgroup.WithContext(ctx)
results := make ([][]byte , len (urls))
for i, url := range urls {
i, url := i, url
g.Go(func () error {
data, err := FetchWithTimeout(ctx, url)
if err != nil {
return err
}
results[i] = data
return nil
})
}
if err := g.Wait(); err != nil {
return nil , err
}
return results, nil
}
避免 Goroutine 洩漏
func leakyFetch (ctx context.Context, url string ) <-chan []byte {
ch := make (chan []byte )
go func () {
data, _ := fetch(url)
ch <- data
}()
return ch
}
func safeFetch (ctx context.Context, url string ) <-chan []byte {
ch := make (chan []byte , 1 )
go func () {
data, err := fetch(url)
if err != nil {
return
}
select {
case ch <- data:
case <-ctx.Done():
}
}()
return ch
}
介面設計
小而專注的介面
type Reader interface {
Read(p []byte ) (n int , err error )
}
type Writer interface {
Write(p []byte ) (n int , err error )
}
type Closer interface {
Close() error
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}
在使用處定義介面
package service
type UserStore interface {
GetUser(id string ) (*User, error )
SaveUser(user *User) error
}
type Service struct {
store UserStore
}
使用型別斷言的可選行為 type Flusher interface {
Flush() error
}
func WriteAndFlush (w io.Writer, data []byte ) error {
if _, err := w.Write(data); err != nil {
return err
}
if f, ok := w.(Flusher); ok {
return f.Flush()
}
return nil
}
套件組織
標準專案結構 myproject/
├── cmd/
│ └── myapp/
│ └── main.go # 進入點
├── internal/
│ ├── handler/ # HTTP handlers
│ ├── service/ # 業務邏輯
│ ├── repository/ # 資料存取
│ └── config/ # 設定
├── pkg/
│ └── client/ # 公開 API 客戶端
├── api/
│ └── v1/ # API 定義(proto、OpenAPI)
├── testdata/ # 測試 fixtures
├── go.mod
├── go.sum
└── Makefile
套件命名
package http
package json
package user
package httpHandler
package json_parser
package userService
避免套件層級狀態
var db *sql.DB
func init () {
db, _ = sql.Open("postgres" , os.Getenv("DATABASE_URL" ))
}
type Server struct {
db *sql.DB
}
func NewServer (db *sql.DB) *Server {
return &Server{db: db}
}
結構設計
Functional Options 模式 type Server struct {
addr string
timeout time.Duration
logger *log.Logger
}
type Option func (*Server)
func WithTimeout (d time.Duration) Option {
return func (s *Server) {
s.timeout = d
}
}
func WithLogger (l *log.Logger) Option {
return func (s *Server) {
s.logger = l
}
}
func NewServer (addr string , opts ...Option) *Server {
s := &Server{
addr: addr,
timeout: 30 * time.Second,
logger: log.Default(),
}
for _, opt := range opts {
opt(s)
}
return s
}
server := NewServer(":8080" ,
WithTimeout(60 *time.Second),
WithLogger(customLogger),
)
嵌入用於組合 type Logger struct {
prefix string
}
func (l *Logger) Log(msg string ) {
fmt.Printf("[%s] %s\n" , l.prefix, msg)
}
type Server struct {
*Logger
addr string
}
func NewServer (addr string ) *Server {
return &Server{
Logger: &Logger{prefix: "SERVER" },
addr: addr,
}
}
s := NewServer(":8080" )
s.Log("Starting..." )
記憶體與效能
已知大小時預分配 Slice
func processItems (items []Item) []Result {
var results []Result
for _, item := range items {
results = append (results, process(item))
}
return results
}
func processItems (items []Item) []Result {
results := make ([]Result, 0 , len (items))
for _, item := range items {
results = append (results, process(item))
}
return results
}
頻繁分配使用 sync.Pool var bufferPool = sync.Pool{
New: func () interface {} {
return new (bytes.Buffer)
},
}
func ProcessRequest (data []byte ) []byte {
buf := bufferPool.Get().(*bytes.Buffer)
defer func () {
buf.Reset()
bufferPool.Put(buf)
}()
buf.Write(data)
return buf.Bytes()
}
避免迴圈中的字串串接
func join (parts []string ) string {
var result string
for _, p := range parts {
result += p + ","
}
return result
}
func join (parts []string ) string {
var sb strings.Builder
for i, p := range parts {
if i > 0 {
sb.WriteString("," )
}
sb.WriteString(p)
}
return sb.String()
}
func join (parts []string ) string {
return strings.Join(parts, "," )
}
Go 工具整合
基本指令
go build ./...
go run ./cmd/myapp
go test ./...
go test -race ./...
go test -cover ./...
go vet ./...
staticcheck ./...
golangci-lint run
go mod tidy
go mod verify
gofmt -w .
goimports -w .
建議的 Linter 設定(.golangci.yml) linters:
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
- gofmt
- goimports
- misspell
- unconvert
- unparam
linters-settings:
errcheck:
check-type-assertions: true
govet:
check-shadowing: true
issues:
exclude-use-default: false
快速參考:Go 慣用語 慣用語 描述 接受介面,回傳結構 函式接受介面參數,回傳具體類型 錯誤是值 將錯誤視為一等值,而非例外 不要透過共享記憶體通訊 使用 channel 在 goroutine 間協調 讓零值有用 類型應無需明確初始化即可工作 一點複製比一點依賴好 避免不必要的外部依賴 清晰優於聰明 優先考慮可讀性而非聰明 gofmt 不是任何人的最愛但是所有人的朋友 總是用 gofmt/goimports 格式化 提早返回 先處理錯誤,保持快樂路徑不縮排
要避免的反模式
func process () (result int , err error ) {
return
}
func GetUser (id string ) *User {
user, err := db.Find(id)
if err != nil {
panic (err)
}
return user
}
type Request struct {
ctx context.Context
ID string
}
func ProcessRequest (ctx context.Context, id string ) error {
}
type Counter struct { n int }
func (c Counter) Value() int { return c.n }
func (c *Counter) Increment() { c.n++ }
記住 :Go 程式碼應該以最好的方式無聊 - 可預測、一致且易於理解。有疑慮時,保持簡單。