Goku

ابزارها و بهینه‌سازی در زبان برنامه‌نویسی Go

این جزوه به بررسی جامع ابزارها و تکنیک‌های بهینه‌سازی در Go می‌پردازد. Go با ابزارهای داخلی و خارجی قدرتمند، امکان پروفایلینگ، مدیریت حافظه، ساخت برنامه‌های کارآمد، و یکپارچه‌سازی با فرآیندهای توسعه را فراهم می‌کند. تمام موضوعات درخواستی با جزئیات کامل و مثال‌های عملی شرح داده شده‌اند.


1. پروفایلینگ و دیباگ

پروفایلینگ و دیباگ برای شناسایی گلوگاه‌های عملکرد و اشکالات برنامه ضروری هستند. Go ابزارهای داخلی مثل pprof، trace، و go tool را ارائه می‌دهد.

1.1. استفاده از pprof

مفهوم

pprof ابزاری برای پروفایلینگ برنامه‌های Go است که اطلاعاتی درباره مصرف CPU، حافظه، و goroutine‌ها ارائه می‌دهد.

فعال‌سازی pprof

پکیج net/http/pprof را به برنامه اضافه کنید:

package main

import (
    "log"
    "net/http"
    _ "net/http/pprof"
)

func main() {
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()
    // کد برنامه
    select {}
}

جمع‌آوری پروفایل

تحلیل

در محیط pprof:

مثال عملی

فرض کنید برنامه‌ای دارید که CPU زیادی مصرف می‌کند:

package main

import (
    "net/http"
    _ "net/http/pprof"
)

func heavyComputation() {
    for i := 0; i < 1000000; i++ {
        _ = i * i
    }
}

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        heavyComputation()
        w.Write([]byte("Done"))
    })
    http.ListenAndServe(":8080", nil)
}
  1. اجرا: go run main.go
  2. پروفایل CPU: go tool pprof http://localhost:6060/debug/pprof/profile
  3. تحلیل: top نشان می‌دهد heavyComputation منابع زیادی مصرف می‌کند.

1.2. استفاده از trace

trace برای تحلیل اجرای برنامه در سطح goroutine‌ها و زمان‌بندی استفاده می‌شود.

جمع‌آوری

package main

import (
    "log"
    "os"
    "runtime/trace"
)

func main() {
    f, err := os.Create("trace.out")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()

    if err := trace.Start(f); err != nil {
        log.Fatal(err)
    }
    defer trace.Stop()

    // کد برنامه
    for i := 0; i < 10; i++ {
        go func() {
            time.Sleep(time.Millisecond * 100)
        }()
    }
    time.Sleep(time.Second)
}

تحلیل

go tool trace trace.out

این دستور یک رابط وب باز می‌کند که شامل:

1.3. استفاده از go tool

go tool ابزارهای مختلفی برای دیباگ ارائه می‌دهد:

1.4. نکات پیشرفته

1.5. خطاهای رایج


2. مدیریت حافظه

مدیریت حافظه در Go توسط Garbage Collector (GC) انجام می‌شود، اما تکنیک‌هایی مثل sync.Pool و بهینه‌سازی GC می‌توانند کارایی را بهبود دهند.

2.1. استفاده از sync.Pool

مفهوم

sync.Pool برای مدیریت اشیاء موقت و کاهش فشار روی GC استفاده می‌شود. مناسب برای اشیائی که مکرراً ایجاد و دور ریخته می‌شوند.

مثال

package main

import (
    "bytes"
    "fmt"
    "sync"
)

var pool = sync.Pool{
    New: func() interface{} {
        return &bytes.Buffer{}
    },
}

func main() {
    buf := pool.Get().(*bytes.Buffer)
    buf.WriteString("Hello")
    fmt.Println(buf.String())
    buf.Reset()
    pool.Put(buf)
}

نکات

2.2. بهینه‌سازی Garbage Collection

نحوه کار GC

تنظیم

export GOGC=200
go run main.go

تکنیک‌های بهینه‌سازی

مثال

package main

import (
    "fmt"
    "runtime"
)

func main() {
    var ms runtime.MemStats
    runtime.ReadMemStats(&ms)
    fmt.Printf("Heap Alloc: %v bytes\n", ms.HeapAlloc)

    // تخصیص زیاد
    for i := 0; i < 1000000; i++ {
        _ = make([]byte, 100)
    }

    runtime.ReadMemStats(&ms)
    fmt.Printf("Heap Alloc after: %v bytes\n", ms.HeapAlloc)

    runtime.GC() // اجرای دستی GC (فقط برای تست)
}

2.3. نکات پیشرفته

2.4. خطاهای رایج


3. کامپایل و بیلد

Go فرآیند ساخت ساده‌ای دارد، اما تکنیک‌هایی برای بهینه‌سازی اندازه باینری و cross-compilation وجود دارد.

3.1. ساخت باینری

دستور پایه

go build -o myapp main.go

بهینه‌سازی

3.2. Cross-Compilation

برای ساخت باینری برای سیستم‌عامل‌ها و معماری‌های دیگر:

GOOS=linux GOARCH=amd64 go build -o myapp-linux main.go
GOOS=windows GOARCH=amd64 go build -o myapp.exe main.go

مثال

ساخت برای لینوکس از مک:

GOOS=linux GOARCH=amd64 go build -o myapp-linux main.go

3.3. بهینه‌سازی اندازه

3.4. نکات پیشرفته

3.5. خطاهای رایج


4. لینت و فرمت کد

لینت و فرمت کد برای حفظ کیفیت و خوانایی کد ضروری هستند.

4.1. استفاده از gofmt

gofmt ابزار استاندارد برای فرمت کد است.

gofmt -w main.go

4.2. استفاده از golint

golint پیشنهادهایی برای بهبود سبک کد ارائه می‌دهد.

نصب

go install golang.org/x/lint/golint@latest

اجرا

golint ./...

4.3. استفاده از staticcheck

staticcheck ابزار پیشرفته‌تری برای تحلیل کد است.

نصب

go install honnef.co/go/tools/cmd/staticcheck@latest

اجرا

staticcheck ./...

مثال

package main

func main() {
    x := 1
    // x استفاده نمی‌شود
}
staticcheck main.go
main.go:3:6: x is unused (U1000)

4.4. نکات پیشرفته

4.5. خطاهای رایج


5. CI/CD برای Go

CI/CD (Continuous Integration/Continuous Deployment) فرآیند خودکارسازی تست، بیلد، و استقرار است.

5.1. تنظیم GitHub Actions

GitHub Actions برای اجرای خودکار وظایف CI/CD استفاده می‌شود.

مثال Workflow

name: Go CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Set up Go
      uses: actions/setup-go@v5
      with:
        go-version: '1.20'
    - name: Install dependencies
      run: go mod download
    - name: Run tests
      run: go test -v ./...
    - name: Run linters
      uses: golangci/golangci-lint-action@v6
      with:
        version: latest
    - name: Build
      run: go build -o myapp

توضیحات

5.2. داکرایز کردن برنامه‌ها

داکر برای بسته‌بندی و استقرار برنامه‌ها استفاده می‌شود.

Dockerfile

FROM golang:1.20 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp

FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]

ساخت و اجرا

docker build -t myapp .
docker run -p 8080:8080 myapp

Multi-Stage Build

5.3. نکات پیشرفته

5.4. خطاهای رایج


6. بهترین شیوه‌ها و نکات


7. نتیجه‌گیری

این جزوه تمام جنبه‌های ابزارها و بهینه‌سازی در Go را با جزئیات کامل پوشش داد. از پروفایلینگ با pprof و trace تا مدیریت حافظه با sync.Pool، ساخت باینری‌های بهینه، لینت کد، و تنظیم CI/CD، هر بخش با مثال‌های عملی و نکات پیشرفته ارائه شد. برای یادگیری عمیق‌تر: