Go modülleri, Go dilinin bağımlılık yönetiminde devrim yaratan, modern ve standart bir yaklaşımdır. Go 1.11 ile tanıtılan ve Go 1.13 itibarıyla varsayılan bağımlılık yönetim aracı haline gelen modüller, geliştiricilerin projelerini daha organize, sürdürülebilir ve tekrarlanabilir bir şekilde yönetmelerini sağlar. GOPATH bazlı eski sistemin getirdiği zorlukları (örneğin, farklı projeler için farklı bağımlılık versiyonlarını yönetme kabiliyetsizliği) aşmak amacıyla tasarlanmışlardır. Bir Go modülü, tek bir sürümleme birimi olarak tanımlanır ve bağımlılıklarını `go.mod` dosyası aracılığıyla deklaratif olarak belirtir. Bu sistem, projelerinizin her zaman doğru bağımlılık setine sahip olmasını garanti eder.
Yeni bir Go projesine başlarken veya mevcut bir projeyi modüllere taşırken yapılması gereken ilk adım, proje dizininin kökünde `go mod init` komutunu çalıştırmaktır.
Bu komut, projenizin bir Go modülü olduğunu belirten ve modülünüzün yolu ile bağımlılıklarını içeren `go.mod` adında bir dosya oluşturur. `ornekmodul` yerine kendi modülünüzün yolunu (genellikle VCS yolunuzu, örneğin `github.com/kullaniciadi/projeadi`) belirtmelisiniz. Oluşturulan `go.mod` dosyası başlangıçta basit bir yapıya sahip olacaktır:
Burada `module ornekmodul` modülünüzün yolunu tanımlar ve `go 1.20` ise bu modülün Go 1.20 veya daha yeni bir Go sürümüyle yazıldığını belirtir. Bu, Go araçlarının doğru dil özelliklerini ve standart kütüphane davranışlarını kullanmasını sağlar.
`go.mod` dosyası, bir Go modülünün kalbidir. İçerisinde projenin tüm doğrudan ve dolaylı bağımlılıkları, minimum Go sürümü ve bazen de bağımlılık çakışmalarını yönetmek için kullanılan `replace` veya `exclude` direktifleri bulunur.
`go.mod` dosyasına ek olarak, `go mod init` veya `go get` gibi komutlar çalıştırıldığında otomatik olarak `go.sum` adında bir dosya daha oluşturulur. Bu dosya, indirilen her bağımlılığın ve onun her bir modülünün kriptografik karmalarını (hashlerini) içerir.
`go.sum` dosyasının ana amacı, güvenlik ve tekrarlanabilirlik sağlamaktır. Go aracı, bir bağımlılığı indirirken veya kullanırken, `go.sum` dosyasındaki karma ile indirilen paketin karmasını karşılaştırır. Eğer karmalar eşleşmezse, Go bir hata verir. Bu, kötü niyetli müdahalelere veya paketlerin bozulmasına karşı koruma sağlar.
Eğer belirli bir versiyonu veya dalı almak isterseniz `go get` komutunu kullanabilirsiniz:
Bağımlılıklarınızda değişiklikler yaptıktan (ekleme, silme, versiyon güncelleme) sonra `go mod tidy` komutunu çalıştırmak iyi bir uygulamadır.
Bu komut, projenizin kaynak kodunda gerçekten kullanılan tüm bağımlılıkları `go.mod` dosyasına ekler ve artık kullanılmayanları kaldırır. Ayrıca `go.sum` dosyasını da günceller, böylece her iki dosya da senkronize kalır. `go mod tidy` aynı zamanda bağımlılık ağacınızdaki tüm dolaylı bağımlılıkların da doğru bir şekilde kaydedilmesini sağlar.
`go mod graph`: Modül bağımlılık grafiğini gösterir. Hangi modülün hangi bağımlılığa sahip olduğunu görselleştirmek için kullanışlıdır.
`go mod verify`: İndirilen modüllerin `go.sum` dosyasındaki karmalarıyla eşleştiğini doğrular. Bağımlılıklarınızın bozulmadığından emin olmak için kullanılabilir.
`go mod vendor`: Tüm modül bağımlılıklarını projenizin `vendor/` dizinine kopyalar. Özellikle kapalı ağ ortamlarında veya derleme ortamının dış bağımlılıklara erişimi kısıtlı olduğunda yararlıdır.
Vendoring kullandığınızda, `go build` gibi komutlar varsayılan olarak `vendor/` dizinindeki bağımlılıkları kullanır. Go Dokümantasyonu Vendoring hakkında daha fazla bilgi sağlar.
Go modülleri Semantik Sürümleme (SemVer) ilkelerini benimser. Bir bağımlılığın majör versiyonu (`v1`, `v2`, `v3` vb.) değiştiğinde, Go bu değişikliği bağımlılığın yolu içinde belirtir (örneğin, `github.com/foo/bar/v2`). Bu, farklı majör versiyonların aynı anda bir projede bulunmasına ve çakışma yaşanmamasına olanak tanır.
Önemli bir nokta şudur: `v0` veya `v1` dışındaki bir majör versiyon yayınlıyorsanız (örneğin `v2`), modül yolunuza `/vN` eklemeyi unutmayın. Örneğin, `module github.com/my/project/v2`. Bu, Go'nun farklı majör versiyonları ayrı modüller olarak tanımasını sağlar ve bağımlılık yönetimi sırasında karışıklığı önler.
Kurumsal ortamlarda veya özel depolarda barındırılan modülleri kullanmak genellikle bir gerekliliktir. Go, bu tür senaryolar için `GOPRIVATE` ve `GONOPROXY` gibi ortam değişkenleri sağlar.
Yeni bir Go projesine başlarken veya mevcut bir projeyi modüllere taşırken yapılması gereken ilk adım, proje dizininin kökünde `go mod init` komutunu çalıştırmaktır.
Kod:
go mod init ornekmodul
Kod:
module ornekmodul
go 1.20
`go.mod` dosyası, bir Go modülünün kalbidir. İçerisinde projenin tüm doğrudan ve dolaylı bağımlılıkları, minimum Go sürümü ve bazen de bağımlılık çakışmalarını yönetmek için kullanılan `replace` veya `exclude` direktifleri bulunur.
- module: Modülün ana yolunu belirtir. Genellikle bir VCS (Version Control System) deposu yoluyla eşleşir.
- go: Bu modülün geliştirildiği Go sürümünü gösterir.
- require: Modülün doğrudan bağımlı olduğu paketleri ve bunların istenen versiyonlarını listeler. Örneğin: `require github.com/go-sql-driver/mysql v1.6.0`. Versiyonlar genellikle Semantik Sürümleme (SemVer) kurallarına uyar.
- exclude: Belirli bir bağımlılığın belirli bir sürümünün kullanılmamasını sağlamak için kullanılır. Nadiren ihtiyaç duyulur ve genellikle bağımlılık ağacında sorunlu bir alt bağımlılık olduğunda devreye girer.
- replace: Bir bağımlılığı başka bir yoldaki veya yerel dosya sistemindeki bir sürümle değiştirmek için kullanılır. Genellikle geliştirme aşamasında yerel bir bağımlılık üzerinde çalışırken veya bir bağımlılığın upstream versiyonunda bir hata olduğunda ve geçici bir düzeltme gerektiğinde kullanılır. Örneğin: `replace github.com/ornek/bagimlilik => ../yerel/bagimlilik`.
`go.mod` dosyasına ek olarak, `go mod init` veya `go get` gibi komutlar çalıştırıldığında otomatik olarak `go.sum` adında bir dosya daha oluşturulur. Bu dosya, indirilen her bağımlılığın ve onun her bir modülünün kriptografik karmalarını (hashlerini) içerir.
Kod:
github.com/go-sql-driver/mysql v1.6.0 h1:Jk+1B+m/Q9x+...
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:N+1O+n/P9y+...
Go modülleri ile bağımlılık yönetimi oldukça basittir. Projenizde yeni bir paketi kullanmaya başladığınızda ve onu import ettiğinizde, Go aracı bir sonraki `go build`, `go test` veya `go run` komutunda otomatik olarak bu bağımlılığı indirir ve `go.mod` dosyasına ekler."Go modüllerinin en önemli özelliklerinden biri, bağımlılıkların güvenli ve deterministik bir şekilde yönetilmesidir. `go.sum` dosyası, bu güvenliğin temel direklerinden biridir."
Kod:
import "github.com/sirupsen/logrus"
Kod:
go get github.com/sirupsen/logrus@v1.8.1
go get github.com/sirupsen/logrus@master
Kod:
go mod tidy
`go mod graph`: Modül bağımlılık grafiğini gösterir. Hangi modülün hangi bağımlılığa sahip olduğunu görselleştirmek için kullanışlıdır.
`go mod verify`: İndirilen modüllerin `go.sum` dosyasındaki karmalarıyla eşleştiğini doğrular. Bağımlılıklarınızın bozulmadığından emin olmak için kullanılabilir.
`go mod vendor`: Tüm modül bağımlılıklarını projenizin `vendor/` dizinine kopyalar. Özellikle kapalı ağ ortamlarında veya derleme ortamının dış bağımlılıklara erişimi kısıtlı olduğunda yararlıdır.
Kod:
go mod vendor
Go modülleri Semantik Sürümleme (SemVer) ilkelerini benimser. Bir bağımlılığın majör versiyonu (`v1`, `v2`, `v3` vb.) değiştiğinde, Go bu değişikliği bağımlılığın yolu içinde belirtir (örneğin, `github.com/foo/bar/v2`). Bu, farklı majör versiyonların aynı anda bir projede bulunmasına ve çakışma yaşanmamasına olanak tanır.
Önemli bir nokta şudur: `v0` veya `v1` dışındaki bir majör versiyon yayınlıyorsanız (örneğin `v2`), modül yolunuza `/vN` eklemeyi unutmayın. Örneğin, `module github.com/my/project/v2`. Bu, Go'nun farklı majör versiyonları ayrı modüller olarak tanımasını sağlar ve bağımlılık yönetimi sırasında karışıklığı önler.
Kurumsal ortamlarda veya özel depolarda barındırılan modülleri kullanmak genellikle bir gerekliliktir. Go, bu tür senaryolar için `GOPRIVATE` ve `GONOPROXY` gibi ortam değişkenleri sağlar.
- `GOPRIVATE`: Go'nun bu yollar altındaki modüller için bir proxy sunucusu kullanmamasını ve onları doğrudan indirmesini sağlar. Ayrıca bu modüllerin `go.sum` dosyasına yazılmamasını sağlar. Virgülle ayrılmış bir liste olarak birden fazla değer alabilir (örneğin, `github.com/mycorp/*,bitbucket.org/mycorp/*`).
- `GOPROXY`: Go modül proxy sunucularının adreslerini belirtir. Varsayılan olarak Go, proxy.golang.org adresini kullanır. Kendi özel proxy'nizi de buraya ekleyebilirsiniz. Örneğin, `GOPROXY=https://myproxy.com,direct`. `direct` değeri, proxy'ler başarısız olduğunda doğrudan VCS'den indirme denemesini sağlar.
- Düzenli `go mod tidy` çalıştırın: Bağımlılıklarınızın her zaman güncel ve doğru olduğundan emin olmak için her bağımlılık değişikliğinden veya önemli kod değişikliğinden sonra `go mod tidy` çalıştırmayı alışkanlık haline getirin.
- Sürüm kontrol sistemine `go.mod` ve `go.sum` dosyalarını dahil edin: Bu dosyalar projenizin tekrarlanabilirliğini ve bütünlüğünü sağlar. Asla `.gitignore` içine almayın.
- Küçük ve odaklı modüller oluşturun: Go'nun felsefesine uygun olarak, modüllerinizi tek bir amaca hizmet edecek şekilde tasarlayın. Bu, bağımlılık yönetimini kolaylaştırır ve derleme sürelerini kısaltır.
- Versiyon sabitleme konusunda dikkatli olun: `go get` ile belirli bir versiyonu (örn. `@v1.2.3`) belirtmek iyi bir uygulama olsa da, gereksiz yere bağımlılıkları sabitlemek yerine `go mod tidy`'nin minimum sürüm seçimini kullanmaya güvenmek genellikle daha iyidir. Yalnızca belirli bir nedenden dolayı (örn. bir güvenlik açığı veya bug fix) versiyonu sabitleyin.
- Proxy kullanmayı düşünün: Go modül proxy'leri, bağımlılık indirme hızını artırır ve güvenilirliği sağlar.
- `go.sum` doğrulama hatası: Bu genellikle `go.sum` dosyasındaki karma değerinin indirilen paketin karmasıyla eşleşmemesinden kaynaklanır. Bu, ya paket sunucusunda bir değişiklik (kötü niyetli veya değil) ya da yerel olarak dosyaların bozulmasından olabilir. Genellikle `go clean --modcache` komutuyla modül önbelleğini temizleyip sonra tekrar `go mod tidy` veya `go build` çalıştırmak sorunu çözer.
- `module xxx not found`: Bu hata, Go'nun belirtilen modülü bulamadığı anlamına gelir. Nedenleri şunlar olabilir: modül yolu yanlış, `GOPRIVATE` ayarları eksik veya yanlış, veya internet erişimi yok. `go.mod` dosyasını kontrol edin ve `GOPRIVATE` ortam değişkeninizin doğru ayarlandığından emin olun.
- Depo erişim sorunları: Özellikle özel depolardan modül indirirken kimlik doğrulama sorunları yaşanabilir. SSH anahtarlarınızın doğru yapılandırıldığından veya HTTPS kimlik bilgilerinizin mevcut olduğundan emin olun.