Go, kodunuzu biçimlendiren, şüpheli yapıları bulan, belge gösteren ve eski kalıpları modernleştiren araçlarla birlikte gelir; hepsi go komutunun alt komutlarıdır. gofmt (paket düzeyinde go fmt) kodu tek bir standart biçime sokar, go vet derleyicinin yakalamadığı olası hataları raporlar, go doc bir paketin ya da sembolün belge yorumunu terminalde gösterir, Go 1.26 ile yeniden yazılan go fix ise kodu yeni dil ve kütüphane özelliklerine otomatik taşır. go env ortam ayarlarını okur, go help her komutun ayrıntılı yardımını verir.
Bu yazıda her aracı Effective Go, Go Blog'daki gofmt ve go fix yazıları, Go Doc Comments belgesi, ilgili sürüm notları ve Go 1.27.3 ile gelen go help çıktılarına dayanarak, gerçek çıktılarıyla gösteriyoruz. Testleri çalıştıran go test Go test yazma rehberi yazısında, derleme ve kurulum komutları go build ve çapraz derleme yazısında ele alınıyor. Öğrenme sırasının tamamı için Go öğrenme rehberi sayfasına bakabilirsiniz.
gofmt ve go fmt: tartışmasız tek biçim

Effective Go biçimlendirme konusunu şöyle özetler: biçim tartışmaları en çok tartışılan ama en az önemli konulardır ve Go bu işi makineye bırakır. gofmt bir Go programını okur ve standart girinti ile hizalamayla yeniden yazar; gerekirse yorumları da yeniden düzenler. Kurallar kısadır: girinti için sekme kullanılır, satır uzunluğu sınırı yoktur, if, for ve switch parantez gerektirmez. Standart kütüphanedeki tüm kod gofmt ile biçimlendirilmiştir.
Elle hızlıca yazılmış, biçimsiz bir dosyayla başlayalım:
package main
import "fmt"
type Urun struct{
Ad string // ürün adı
Fiyat int // kuruş
}
func main(){
u:=Urun{Ad:"Kalem",Fiyat:1250}
if u.Fiyat>1000 {fmt.Println(u.Ad, "pahalı")}
}gofmt -l biçimi standart olmayan dosyaların adlarını listeler, -d değişikliği fark (diff) olarak gösterir, -w dosyanın üzerine yazar. go fmt ise go help fmt çıktısına göre verilen paketler üzerinde gofmt -l -w çalıştırır ve değiştirdiği dosyaların adını yazar:
$ gofmt -l .
main.go
$ go fmt ./...
main.gopackage main
import "fmt"
type Urun struct {
Ad string // ürün adı
Fiyat int // kuruş
}
func main() {
u := Urun{Ad: "Kalem", Fiyat: 1250}
if u.Fiyat > 1000 {
fmt.Println(u.Ad, "pahalı")
}
}Yapı alanlarının türleri ve yorumları sütun hâlinde hizalandı, operatörlerin çevresine boşluk kondu, tek satırlık if bloğu açıldı ve bildirimler arasına boş satır eklendi. Effective Go'nun da belirttiği gibi alan yorumlarını elle hizalamaya hiç uğraşmanız gerekmez. Bir şeyin nasıl biçimlendirileceğinden emin değilseniz gofmt çalıştırın; sonuç yanlış görünüyorsa belgenin önerisi, kodu yeniden düzenlemek ya da hata bildirmektir, aracın etrafından dolaşmak değil.
gofmt ile mekanik dönüşüm: -r ve -s
Go Blog'daki "go fmt your code" yazısı, makinece biçimlendirilmiş kodun bir avantajını vurgular: kod mekanik olarak dönüştürüldüğünde farklarda ilgisiz biçim gürültüsü oluşmaz. -r bayrağı desen -> yerine biçiminde bir yeniden yazma kuralı alır; desende tek harfli küçük tanımlayıcılar herhangi bir alt ifadeyle eşleşen joker karakterlerdir. Yazıdaki gerçek örnek, bytes.Compare(a, b) == 0 kullanımlarını bytes.Equal(a, b) ile değiştirmektir. Aynı kuralı bir programa uyguladık:
package main
import (
"bytes"
"fmt"
)
func main() {
a, b := []byte("go"), []byte("go")
if bytes.Compare(a, b) == 0 {
fmt.Println("eşit")
}
s := []int{1, 2, 3}
fmt.Println(s[1:len(s)])
}$ gofmt -d -r 'bytes.Compare(a, b) == 0 -> bytes.Equal(a, b)' main.go
diff main.go.orig main.go
--- main.go.orig
+++ main.go
@@ -7,7 +7,7 @@
func main() {
a, b := []byte("go"), []byte("go")
- if bytes.Compare(a, b) == 0 {
+ if bytes.Equal(a, b) {
fmt.Println("eşit")
}
s := []int{1, 2, 3}Aynı dosyada gofmt -d -s çalıştırdığımızda araç s[1:len(s)] ifadesini eşdeğeri olan s[1:] biçimine sadeleştirmeyi önerdi. -r yalnızca ifade düzeyinde basit değişiklikler yapar; tip bilgisine ihtiyaç duyan, daha akıllı dönüşümler için go fix vardır.
- fmt.Println(s[1:len(s)])
+ fmt.Println(s[1:])go vet: derlenen ama yanlış olan kod

go vet, paketler üzerinde cmd/vet aracını çalıştırır. Bu araç, derleyicinin kabul ettiği ama büyük olasılıkla hatalı olan yapıları arar: biçim dizgisiyle uyuşmayan Printf argümanları, değerle kopyalanan kilitler, ulaşılamayan kod gibi. Aşağıdaki program sorunsuz derleniyor ve çalışıyor, ama dört farklı hata barındırıyor:
package main
import (
"fmt"
"sync"
"time"
)
type Sayac struct {
mu sync.Mutex
n int
}
func yazdir(s Sayac) {
fmt.Println(s.n)
}
func main() {
var s Sayac
yazdir(s)
fmt.Printf("%d ürün\n", "üç")
fmt.Println(time.Now().Format("2006-02-01"))
return
fmt.Println("buraya ulaşılmaz")
}$ go build . && echo derlendi
derlendi
$ go vet .
main.go:14:15: yazdir passes lock by value: example.com/vet.Sayac contains sync.Mutex
main.go:20:9: call of yazdir copies lock value: example.com/vet.Sayac contains sync.Mutex
main.go:21:14: fmt.Printf format %d has arg "üç" of wrong type string
main.go:22:33: 2006-02-01 should be 2006-01-02
main.go:24:2: unreachable code
$ echo $?
1Her satır bir analizcinin bulgusudur. copylocks, içinde sync.Mutex bulunan bir yapının değerle kopyalandığını söylüyor; kopyalanan kilit asıl kilidi korumaz (doğru kullanım için Go sync, Mutex ve WaitGroup). printf, %d fiiline metin verildiğini yakaladı (fiiller için Go fmt ve Printf). timeformat, gün ile ayın yer değiştirdiği 2006-02-01 düzenini fark etti; Go'nun referans tarihi 2006-01-02'dir (bkz. Go time paketi). unreachable ise return sonrasındaki satırı gösterdi. go vet bulgu varsa sıfırdan farklı kodla çıkar; bu yüzden CI adımlarında doğrudan kullanılabilir.
Kayıtlı analizcilerin listesini go tool vet help, bir analizcinin açıklamasını go tool vet help unreachable verir. Belirli analizcileri açıp kapatmak için -ADI ve -ADI=false bayrakları kullanılır; go vet -printf=false . çalıştırdığımızda printf bulgusu listeden çıktı, diğer dördü kaldı. Go 1.27'de go help vet şu bayrakları da listeliyor: bulgunun çevresindeki satırları gösteren -c, JSON çıktı için -json, önerilen düzeltmeyi uygulayan -fix ve düzeltmeyi fark olarak gösteren -diff. -vettool ile golang.org/x/tools üzerinde yazılmış başka bir analiz aracı da çalıştırılabilir.
| Analizci | Ne arar |
|---|---|
| printf | Printf ailesinde biçim dizgisi ile argüman uyuşmazlığı |
| copylocks | Değerle kopyalanan kilitler |
| loopclosure | İç içe fonksiyonlardan döngü değişkenine başvurular |
| lostcancel | context.WithCancel ile dönen cancel fonksiyonunun çağrılmaması |
| structtag | reflect.StructTag.Get kurallarına uymayan alan etiketleri |
| unusedresult | Sonucu kullanılması gereken bazı çağrıların sonucunun atılması |
| tests | Test, benchmark, fuzz ve örnek bildirimlerindeki yaygın hatalar |
| stdversion | go satırına göre fazla yeni standart kütüphane sembolleri |
| waitgroup | sync.WaitGroup kullanım hataları |
Sürüm notları her sürümde yeni denetimler ekler. Go 1.24, test bildirimlerindeki hataları bulan tests analizcisini ekledi ve printf denetimini, sabit olmayan bir biçim dizgisinin tek argüman olarak verildiği fmt.Printf(s) çağrılarını da raporlayacak şekilde genişletti. Go 1.25, yanlış yerdeki WaitGroup.Add çağrıları için waitgroup ve IPv6 ile çalışmayan fmt.Sprintf("%s:%d", host, port) adres kalıbı için hostport analizcilerini getirdi. Go 1.27'de ise printf analizcisi, %w ile sarmalanan değerin *E tipinde olduğu ve E'nin kendisinin error uyguladığı çağrıları raporluyor; bu tür sarmalama errors.Is gibi denetimlerin yanlış sonuç vermesine yol açabilir (bkz. Go hata yönetimi).
go doc: belge terminalde
go doc, bir paketin, sabitin, fonksiyonun, tipin, değişkenin, metodun ya da yapı alanının belge yorumunu ve altındaki öğelerin tek satırlık özetini yazar. Argüman Go sözdizimine benzer: go doc strings.Cut, go doc json.Decoder.Decode. Argümandaki küçük harfler her iki harfle de eşleştiği için go doc json.decoder.decode da çalışır. Paket yolunun son kısmını yazmak yeterlidir: json, encoding/json anlamına gelir.
$ go doc strings.Cut
package strings // import "strings"
func Cut(s, sep string) (before, after string, found bool)
Cut slices s around the first instance of sep, returning the text before and
after sep. The found result reports whether sep appears in s. If sep does
not appear in s, cut returns s, "", false.
$ go doc -short strings | head -3
func Clone(s string) string
func Compare(a, b string) int
func Contains(s, substr string) boolKendi paketiniz için de aynı komut çalışır; argümansız go doc bulunduğunuz dizindeki paketi gösterir. Test yazısındaki hesap paketinde çalıştırdığımızda paket yorumu ve dışa aktarılan adlar listelendi, dışa aktarılmayan yuvarla görünmedi (onu görmek için -u gerekir):
$ go doc
package hesap // import "example.com/hesap"
Package hesap, basit fiyat hesapları yapar.
var ErrNegatif = errors.New("tutar negatif olamaz")
func Indirim(kurus, yuzde int) (int, error)
func Slug(baslik string) string
$ go doc Indirim
package hesap // import "example.com/hesap"
func Indirim(kurus, yuzde int) (int, error)
Indirim, kuruş cinsinden tutara yüzde indirimi uygular.Go 1.27 sürüm notlarına göre go doc artık -ex bayrağıyla çalıştırılabilir örnekleri listeliyor ve bir örnek adı verildiğinde örneğin kaynak kodunu yorumlarıyla yazdırıyor. Aynı sürümde go doc example.com/pkg@v1.2.3 biçiminde sürümlü sorgu desteği de geldi. Go 1.25 ile eklenen -http ise belgeyi yerel bir HTTP sunucusunda tarayıcıda açar.
$ go doc -ex hesap.ExampleSlug
package main
import (
"fmt"
"example.com/hesap"
)
func main() {
fmt.Println(hesap.Slug("Kış Kampanyası"))
}
Output: kış-kampanyasıgo doc çıktısının kalitesi tamamen yazdığınız yorumlara bağlıdır. Go Doc Comments belgesine göre belge yorumu, üst düzey bir package, const, func, type veya var bildiriminin hemen önünde, arada boş satır olmadan duran yorumdur ve dışa aktarılan her adın bir belge yorumu olmalıdır. Paket yorumu // Package hesap ... biçiminde paket adıyla başlar. Yorumlar yalnızca terminalde değil, pkg.go.dev üzerinde ve gopls aracılığıyla editörlerde de gösterilir. Go 1.26 ile ayrı cmd/doc aracı ve go tool doc kaldırıldı; aynı bayraklarla go doc kullanılır.
go fix: kodu modernleştirmek
Go 1.26 sürüm notlarına göre go fix tamamen yeniden yazıldı ve Go'nun modernleştiricilerinin (modernizers) evi oldu. Eskiden içindeki düzelticilerin hepsi kullanılmaz hâle gelmişti ve kaldırıldı; yeni sürüm go vet ile aynı analiz çatısını kullanır, yani vet'in tanılama veren analizcileri go fix içinde düzeltme önerip uygulayabilir. Düzelticilerin programın davranışını değiştirmemesi hedeflenir. Go Blog'daki "Using go fix to modernize Go code" yazısı, her araç takımı yükseltmesinden sonra projede go fix ./... çalıştırmayı ve değişikliklerin yalnızca go fix düzenlemelerinden oluşması için temiz bir Git durumundan başlamayı önerir. Komut üretilmiş dosyalara dokunan düzeltmeleri atlar.
Aşağıdaki program eski kalıplarla yazıldı ama sorunsuz çalışıyor:
package main
import (
"fmt"
"strings"
)
func yazdir(v interface{}) {
fmt.Println(v)
}
func main() {
for i := 0; i < 3; i++ {
yazdir(i)
}
satir := "ad=Ayşe"
eq := strings.Index(satir, "=")
if eq >= 0 {
fmt.Println(satir[:eq], satir[eq+1:])
}
a, b := 4, 9
buyuk := a
if b > a {
buyuk = b
}
fmt.Println(buyuk)
}-diff bayrağı dosyalara dokunmadan yapılacak değişikliği gösterir (dosya yolu kısaltıldı):
$ go fix -diff ./...
--- .../fix/main.go (old)
+++ .../fix/main.go (new)
@@ -5,23 +5,20 @@
"strings"
)
-func yazdir(v interface{}) {
+func yazdir(v any) {
fmt.Println(v)
}
func main() {
- for i := 0; i < 3; i++ {
+ for i := range 3 {
yazdir(i)
}
satir := "ad=Ayşe"
- eq := strings.Index(satir, "=")
- if eq >= 0 {
- fmt.Println(satir[:eq], satir[eq+1:])
+ before, after, ok := strings.Cut(satir, "=")
+ if ok {
+ fmt.Println(before, after)
}
a, b := 4, 9
- buyuk := a
- if b > a {
- buyuk = b
- }
+ buyuk := max(b, a)
fmt.Println(buyuk)
}Tek komutla dört modernleştirici çalıştı: any boş arayüz yazımını, rangeint üç bölümlü sayaç döngüsünü tamsayı üzerinde range ile, stringscut strings.Index ve dilimleme kalıbını strings.Cut ile, minmax ise if ile yazılmış büyük değer seçimini yerleşik max ile değiştirdi. Modernleştiriciler go.mod dosyasındaki go sürümüne bakar; bu modülde go 1.27.3 yazdığı için Go 1.21 ile gelen max ve Go 1.22 ile gelen tamsayı range kullanılabildi. Sonucu -diff olmadan uygulamak için go fix ./... yazarsınız.
Kullanılabilir düzelticilerin listesini go tool fix help verir; Go 1.27.3'teki listede newexpr (Go 1.26'nın new(ifade) özelliği, bkz. Go 1.26 yenilikleri), waitgroupgo, slicessort, stringsbuilder ve omitzero gibi düzelticiler var. Go 1.27 sürüm notları yeni modernleştiriciler olarak atomictypes, embedlit, slicesbackward ve unsafefuncs düzelticilerini sayar; fmtappendf üslup kaygıları nedeniyle kaldırıldı, waitgroup ise karışıklığı önlemek için waitgroupgo adını aldı. Bu sürümün diğer yenilikleri için Go 1.27 yenilikleri yazısına bakabilirsiniz. Kütüphane yazarları, //go:fix inline yönergesiyle kendi API geçişlerini de go fix aracılığıyla otomatikleştirebilir.
go env ve go help
go env Go ortam bilgisini yazar. Argümansız çalıştırıldığında tüm değişkenleri kabuk betiği biçiminde (Windows'ta toplu iş dosyası biçiminde) basar; değişken adı verirseniz her birinin değerini ayrı satıra yazar. -json çıktıyı JSON yapar, -changed yalnızca varsayılandan farklı olan ayarları gösterir. Bu makinedeki çıktı şöyleydi:
$ go env GOOS GOARCH GOVERSION CGO_ENABLED
windows
amd64
go1.27.3
0
$ go env -json GOOS GOARCH
{
"GOARCH": "amd64",
"GOOS": "windows"
}CGO_ENABLED değerinin 0 çıkması, bu makinede bir C derleyicisi bulunmamasından kaynaklanıyor; bunun sonuçları derleme yazısında anlatılıyor. go env -w AD=DEĞER bir ayarı kalıcı olarak yazar ve go env -u AD geri alır; bu ayarlar GOENV değişkeninin gösterdiği dosyada saklanır. Bir değeri yalnızca tek komut için değiştirmek istiyorsanız, kalıcı ayar yerine komutun önüne ortam değişkeni yazmak (GOOS=linux go build) daha az sürpriz üretir.
Bu yazıdaki her komutun tam belgesi araçla birlikte gelir. go help komutların ve yardım konularının listesini verir; go help build, go help testflag, go help buildconstraint, go help environment ve go help packages en sık başvurulan sayfalardır. Komut düzeyindeki kısa kullanım bilgisi için go vet -h gibi -h bayrağı da kullanılabilir.
Sık yapılan hatalar

- gofmt farkını CI'da yakalamamak:
gofmt -l .çıktısı boş değilse adımı başarısız sayın; böylece biçimsiz kod depoya girmez. - go vet bulgularını uyarı sanmak: vet'in raporladığı kod derlense bile çoğu zaman gerçekten hatalıdır; özellikle
printf,copylocksvelostcancelbulgularını düzeltin. - go fix çıktısını incelemeden birleştirmek: Düzeltmeler davranışı korumak için tasarlanmıştır, ama yine de testlerle doğrulayın ve küçük, ayrı bir commit olarak gönderin.
- Belge yorumunu bildirimden boş satırla ayırmak: Arada boş satır varsa yorum belge sayılmaz ve
go doconu göstermez. - go env -w ile kalıcı ayarı unutmak: Kalıcı yazılan bir
GOFLAGSya daGOOSsonraki tüm komutları etkiler. Ne değiştiğinigo env -changedile görebilirsiniz.
Sık Sorulan Sorular
gofmt ile go fmt arasındaki fark nedir?
gofmt dosyalar üzerinde çalışan biçimlendiricidir ve -d, -r, -s gibi bayraklar alır. go fmt ise paket düzeyinde çalışan bir kısayoldur ve verilen paketlere gofmt -l -w uygular. Özel bayrak gerekiyorsa gofmt komutunu doğrudan kullanın.
go vet ile go test ilişkisi nedir?
go test, testleri çalıştırmadan önce vet analizcilerinin yüksek güvenilirlikli bir alt kümesini otomatik çalıştırır ve sorun bulursa testleri başlatmaz. Tüm analizciler için ayrıca go vet ./... çalıştırmanız gerekir.
go fix kodumu bozabilir mi?
Go 1.26 sürüm notlarına göre düzelticilerin programın davranışını değiştirmemesi beklenir ve böyle bir sorunla karşılaşırsanız hata bildirmeniz istenir. Yine de her değişikliği -diff ile inceleyip testlerinizi çalıştırmak en güvenli yoldur.
Bu araçları editörümde nasıl kullanırım?
Go ekibinin dil sunucusu gopls, Go Doc Comments belgesine göre düzenleme sırasında belgeleri gösterir ve editörler kaydederken biçimlendirme yapabilir. Kurulum editörünüze göre değiştiği için ayrıntılar bu yazının kapsamı dışında.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Go öğrenme rehberi · Go test yazma · go build ve çapraz derleme · Go modül yönetimi · Go 1.27 yenilikleri · Go'da sık karşılaşılan hatalar