این جزوه به بررسی جامع ابزارها و تکنیکهای بهینهسازی در Go میپردازد. Go با ابزارهای داخلی و خارجی قدرتمند، امکان پروفایلینگ، مدیریت حافظه، ساخت برنامههای کارآمد، و یکپارچهسازی با فرآیندهای توسعه را فراهم میکند. تمام موضوعات درخواستی با جزئیات کامل و مثالهای عملی شرح داده شدهاند.
پروفایلینگ و دیباگ برای شناسایی گلوگاههای عملکرد و اشکالات برنامه ضروری هستند. Go ابزارهای داخلی مثل pprof، trace، و go tool را ارائه میدهد.
pprof ابزاری برای پروفایلینگ برنامههای Go است که اطلاعاتی درباره مصرف CPU، حافظه، و goroutineها ارائه میدهد.
پکیج net/http/pprof را به برنامه اضافه کنید:
package main
import (
"log"
"net/http"
_ "net/http/pprof"
)
func main() {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// کد برنامه
select {}
}
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
این دستور 30 ثانیه داده جمعآوری کرده و وارد محیط تعاملی pprof میشود.
go tool pprof http://localhost:6060/debug/pprof/heap
go tool pprof http://localhost:6060/debug/pprof/goroutine
در محیط pprof:
(pprof) top
(pprof) web
(pprof) list main.myFunction
فرض کنید برنامهای دارید که 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)
}
go run main.gogo tool pprof http://localhost:6060/debug/pprof/profiletop نشان میدهد heavyComputation منابع زیادی مصرف میکند.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
این دستور یک رابط وب باز میکند که شامل:
go tool ابزارهای مختلفی برای دیباگ ارائه میدهد:
go tool objdump -s main.main mybinary
go tool nm mybinary
pprof با احتیاط استفاده کنید (با احراز هویت).go run -race main.go
go get -u github.com/go-delve/delve/cmd/dlv
dlv debug main.go
-race.مدیریت حافظه در Go توسط Garbage Collector (GC) انجام میشود، اما تکنیکهایی مثل sync.Pool و بهینهسازی GC میتوانند کارایی را بهبود دهند.
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)
}
Put بازنشانی کنید (مثل buf.Reset()).sync.Pool thread-safe است.GOGC رفتار GC را کنترل میکند (پیشفرض 100):
GOGC=200: GC کمتر اجرا میشود (مصرف حافظه بیشتر).GOGC=50: GC مکرر اجرا میشود (مصرف CPU بیشتر).export GOGC=200
go run main.go
s := make([]int, 0, 1000)
go build -gcflags="-m"
این دستور نشان میدهد کدام متغیرها به heap منتقل میشوند.
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 (فقط برای تست)
}
go tool pprof http://localhost:6060/debug/pprof/heap
runtime.SetFinalizer(obj, func(o *Type) {
// آزادسازی
})
sync.Pool.GOGC بدون تست.Go فرآیند ساخت سادهای دارد، اما تکنیکهایی برای بهینهسازی اندازه باینری و cross-compilation وجود دارد.
go build -o myapp main.go
myapp.go build -ldflags="-s -w" -o myapp
-s: حذف جدول سمبلها.-w: حذف اطلاعات DWARF.upx --brute myapp
برای ساخت باینری برای سیستمعاملها و معماریهای دیگر:
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
go mod tidy
CGO_ENABLED=0 go build -o myapp
CGO_ENABLED=0 GOOS=linux go build -a -ldflags="-extldflags '-static'" -o myapp
// +build prod
package main
go build -tags prod
go build -ldflags="-X main.version=1.0.0" -o myapp
var version string
fmt.Println("Version:", version)
GOOS/GOARCH برای cross-compilation.لینت و فرمت کد برای حفظ کیفیت و خوانایی کد ضروری هستند.
gofmt ابزار استاندارد برای فرمت کد است.
gofmt -w main.go
gofmt را اجرا میکنند.golint پیشنهادهایی برای بهبود سبک کد ارائه میدهد.
go install golang.org/x/lint/golint@latest
golint ./...
main.go:10:1: exported function Foo should have comment or be unexported
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)
pre-commit برای اجرای gofmt و staticcheck استفاده کنید:
```yaml
repos:
revive: جایگزین سریعتر برای golint.golangci-lint: ترکیبی از چندین ابزار لینت:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
golangci-lint run
gofmt قبل از commit.CI/CD (Continuous Integration/Continuous Deployment) فرآیند خودکارسازی تست، بیلد، و استقرار است.
GitHub Actions برای اجرای خودکار وظایف CI/CD استفاده میشود.
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
golangci-lint.داکر برای بستهبندی و استقرار برنامهها استفاده میشود.
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
kubectl apply -f deployment.yaml
go test -tags=integration ./...
go test -coverprofile=coverage.out
go tool cover -html=coverage.out
sync.Pool برای اشیاء پرتکرار و ظرفیت اولیه برای اسلایسها استفاده کنید.-ldflags="-s -w" و CGO_ENABLED=0 برای باینریهای تولید استفاده کنید.این جزوه تمام جنبههای ابزارها و بهینهسازی در Go را با جزئیات کامل پوشش داد. از پروفایلینگ با pprof و trace تا مدیریت حافظه با sync.Pool، ساخت باینریهای بهینه، لینت کد، و تنظیم CI/CD، هر بخش با مثالهای عملی و نکات پیشرفته ارائه شد. برای یادگیری عمیقتر:
https://golang.org/doc/