Modül
Her modern dilin olgun bir bağımlılık yönetim aracına sahiptir. Örneğin Java'nın Gradle'ı, Python'un Pip'i, NodeJs'in Npm'i gibi. İyi bir bağımlılık yönetim aracı geliştiriciler için zaman kazandırabilir ve geliştirme verimliliğini artırabilir. Ancak Go erken dönemde olgun bir bağımlılık yönetim çözümü yoktu. O zaman tüm kod GOPATH dizininde saklanıyordu. Mühendislik projeleri için çok dostane değildi. Sürüm karmaşası, bağımlılıkların yönetilmesi zordu. Bu sorunu çözmek için, büyük topluluk geliştiricileri arasında rekabet başladı. Durum bir süre karmaşıklaştı. Bu süreçte bazı öne çıkanlar ortaya çıktı, örneğin Vendor. Go1.11'e kadar resmi sonunda Go Mod'u resmi bağımlılık yönetim aracı olarak tanıttı. Önceki karmaşık durumu sona erdirdi. Sonraki güncellemelerde sürekli olarak geliştirildi ve eski araçları ortadan kaldırdı. Bugüne kadar, bu makaleyi yazarken, Go sürümü 1.20'ye ulaştı. Bugün neredeyse tüm Go projeleri Go Mod'u kullanıyor. Bu nedenle bu makalede sadece Go Mod tanıtılacak. Resmi Go modülleri için çok detaylı belgeler yazmıştır: Go Modules Reference.
Modül Yazma
Go Module temelde VCS'ye (sürüm kontrol sistemi) dayanır. Bağımlılık indirirken, aslında VCS komutu çalıştırırsınız. Örneğin git. Bu nedenle, yazdığınız kütüphaneyi paylaşmak istiyorsanız, sadece şu üç noktayı yapmanız gerekir:
- Kaynak kod deposu herkese açık erişilebilir olmalı ve VCS aşağıdakilerden biri olmalı
- git
- hg (Mercurial)
- bzr (Bazaar)
- svn
- fossil
- Standartlara uygun bir go mod projesi olmalı
- Semantik sürümleme kurallarına uygun olmalı
Bu nedenle sadece normalde VCS geliştirme kullanmanız, belirli sürümünüz için standartlara uygun Tag eklemeniz yeterlidir. Diğerleri modül adı aracılığıyla yazdığınız kütüphaneyi indirebilir. Aşağıda modül geliştirmenin birkaç adımını örnek ile göstereceğim.
Örnek depo: 246859/hello: say hello (github.com)
Hazırlık
Başlamadan önce sürümünüzün go mod'u tam olarak destekleyecek kadar yeterli olduğundan emin olun (go >= 1.17). Ve Go Module'ü etkinleştirin. Aşağıdaki komutla açıp açmadığınızı kontrol edin
$ go env GO111MODULEEğer etkinleştirilmediyse, aşağıdaki komutla Go Module'ü etkinleştirin
$ go env -w GO111MODULE=onOluşturma
Önce herkese açık erişilebilir bir kaynak kod deposuna ihtiyacınız var. Bunun için birçok seçenek var. Github'u öneririm. Orada hello adında yeni bir proje oluşturun. Depo adı için özel bir kısıtlama yok, ancak özel karakterler kullanmamanız önerilir. Çünkü bu modül adını etkiler.

Oluşturduktan sonra, depo URL'sinin https://github.com/246859/hello olduğunu görebilirsiniz. İlgili go modül adı github.com/246859/hello'dir.

Ardından bunu yerel makineye klonlayın ve go mod init komutu ile modülü başlatın.
$ git clone git@github.com:246859/hello.git
Cloning into 'hello'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (5/5), done.
$ cd hello && go mod init github.com/246859/hello
go: creating new go.mod: module github.com/246859/helloYazma
Ardından geliştirme çalışmasına başlayabilirsiniz. İşlevi çok basit, sadece bir fonksiyon var
// hello.go
package hello
import "fmt"
// Hello returns hello message
func Hello(name string) string {
if name == "" {
name = "world"
}
return fmt.Sprintf("hello %s!", name)
}Birim testi için bir test dosyası yazın
// hello_test.go
package hello_test
import (
"testing"
"fmt"
"github.com/246859/hello"
)
func TestHello(t *testing.T) {
data := "jack"
expected := fmt.Sprintf("hello %s!", data)
result := hello.Hello(data)
if result != expected {
t.Fatalf("expected result %s, but got %s", expected, result)
}
}Ardından hello çıktısı için bir komut satırı programı yazın. İşlevi aynı şekilde çok basit. Komut satırı programı için, standartlara göre proje cmd/app_name/ içinde oluşturulur. Bu nedenle hello komut satırı programı dosyası cmd/hello/ dizininde saklanır. Ardından ilgili kodu içinde yazın.
// cmd/hello/main.go
package main
import (
"flag"
"github.com/246859/hello"
"os"
)
var name string
func init() {
flag.StringVar(&name, "name", "world", "name to say hello")
}
func main() {
flag.Parse()
msg := hello.Hello(name)
_, err := os.Stdout.WriteString(msg)
if err != nil {
os.Stderr.WriteString(err.Error())
}
}Test
Yazdıktan sonra kaynak kodu biçimlendirin ve test edin
$ go fmt && go vet ./...
$ go test -v .
=== RUN TestHello
--- PASS: TestHello (0.00s)
PASS
ok github.com/246859/hello 0.023sKomut satırı programını çalıştırın
$ go run ./cmd/hello -name jack
hello jack!Dokümantasyon
Son olarak, bu kütüphane için kısa ve anlaşılır bir README yazmanız gerekir. Diğer geliştiricilerin nasıl kullanılacağını bir bakışta bilmesini sağlayın
# hello
just say hello
## Install
import code
```bash
go get github.com/246859/hello@latest
```
install cmd
```bash
go install github.com/246859/hello/cmd/hello@latest
```
## Example
Here's a simple example as follows:
```go
package main
import (
"fmt"
"github.com/246859/hello"
)
func main() {
result := hello.Hello("jack")
fmt.Println(result)
}
```Bu çok basit bir README belgesidir. Kendiniz zenginleştirebilirsiniz.
Yükleme
Tüm kodlar yazıldı ve test edildikten sonra, değişiklikleri gönderebilir ve uzak depoya itebilirsiniz.
$ git add go.mod hello.go hello_test.go cmd/ example/ README.md
$ git commit -m "chore(mod): mod init" go.mod
[main 5087fa2] chore(mod): mod init
1 file changed, 3 insertions(+)
create mode 100644 go.mod
$ git commit -m "feat(hello): complete Hello func" hello.go
[main 099a8bf] feat(hello): complete Hello func
1 file changed, 11 insertions(+)
create mode 100644 hello.go
$ git commit -m "test(hello): complete hello testcase" hello_test.go
[main 76e8c1e] test(hello): complete hello testcase
1 file changed, 17 insertions(+)
create mode 100644 hello_test.go
$ git commit -m "feat(hello): complete hello cmd" cmd/hello/
[main a62a605] feat(hello): complete hello cmd
1 file changed, 22 insertions(+)
create mode 100644 cmd/hello/main.go
$ git commit -m "docs(example): add hello example" example/
[main 5c51ce4] docs(example): add hello example
1 file changed, 11 insertions(+)
create mode 100644 example/main.go
$ git commit -m "docs(README): update README" README.md
[main e6fbc62] docs(README): update README
1 file changed, 27 insertions(+), 1 deletion(-)Toplam altı commit çok fazla değil. Commit tamamlandıktan sonra en son commit için bir tag oluşturun
$ git tag v1.0.0
$ git tag -l
v1.0.0
$ git log --oneline
e6fbc62 (HEAD -> main, tag: v1.0.0, origin/main, origin/HEAD) docs(README): update README
5c51ce4 docs(example): add hello example
a62a605 feat(hello): complete hello cmd
76e8c1e test(hello): complete hello testcase
099a8bf feat(hello): complete Hello func
5087fa2 chore(mod): mod init
1f422d1 Initial commitSon olarak uzak depoya itin
$ git push --tags
Enumerating objects: 23, done.
Counting objects: 100% (23/23), done.
Delta compression using up to 16 threads
Compressing objects: 100% (17/17), done.
Writing objects: 100% (21/21), 2.43 KiB | 1.22 MiB/s, done.
Total 21 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (5/5), done.
To github.com:246859/hello.git
1f422d1..e6fbc62 main -> main
* [new tag] v1.0.0 -> v1.0.0İtme tamamlandıktan sonra, bir release oluşturun (bir tag yeterlidir, release sadece github standartlarına uygundur)

Bu şekilde modül yazma tamamlandı. Yukarıdakiler modül geliştirmenin temel sürecidir. Diğer geliştiriciler modül adı aracılığıyla kodu import edebilir veya komut satırı araçlarını yükleyebilir.
Referans
go get ile kütüphaneyi referans alın
$ go get github.com/246859/hello@latest
go: downloading github.com/246859/hello v1.0.0
go: added github.com/246859/hello v1.0.0go install ile komut satırı programını yükleyin
$ go install github.com/246859/hello/cmd/hello@latest && hello -name jack
hello jack!Veya go run ile doğrudan çalıştırın
$ go run -mod=mod github.com/246859/hello/cmd/hello -name jack
hello jack!Bir kütüphane referans alındıktan sonra, Go Package otomatik olarak bir sayfa oluşturur. Bu süreç otomatik olarak tamamlanır, geliştiricinin herhangi bir iş yapmasına gerek yoktur. Örneğin hello kütüphanesinin özel bir belge sayfası vardır. Aşağıdaki resimde gösterildiği gibi.

Modül yükleme hakkında daha fazla detay için, Add a package adresine gidin.
Modül bilgilerini silme hakkında, Removing a package adresine gidin.
Proxy Ayarlama
Go'nun Maven Repo, PyPi, NPM gibi merkezi bir deposu yok, ancak resmi bir proxy deposu var: Go modules services (golang.org). Geliştiricilerin indirdiği modülleri sürüm ve modül adına göre önbelleğe alır. Ancak sunucuları yurtdışında dağıtıldığı için, yerel kullanıcılar için erişim hızı dostane değil. Bu nedenle varsayılan modül proxy adresini değiştirmemiz gerekiyor. Şu anda Çin'de daha iyi olan birkaç tane var:

Burada Qiniu Cloud proxy'sini seçin. Go proxy'yi değiştirmek için aşağıdaki komutu çalıştırın. direct, proxy indirme başarısız olduğunda proxy önbelleğini atlayıp doğrudan kaynak kod deposuna erişmeyi ifade eder.
$ go env -w GOPROXY=https://goproxy.cn,directProxy başarıyla değiştirildikten sonra, gelecekte bağımlılık indirme çok hızlı olacaktır.
Bağımlılık İndirme
Proxy'yi değiştirdikten sonra, bir üçüncü taraf bağımlılık yüklemeyi deneyin. Go resmi için özel bağımlılık sorgu web sitesi var: Go Packages.
Kod Referansı
İçinde ünlü Web framework'ü Gin'i arayın.

Burada birçok arama sonucu görünecektir. Üçüncü taraf bağımlılık kullanırken, referans sayısı ve güncelleme zamanına göre bu bağımlılığın kullanılıp kullanılmayacağına karar vermelisiniz. Burada doğrudan ilkini seçin

İlgili sayfaya girdikten sonra, bunun bağımlılığın bir belge sayfası olduğunu görebilirsiniz. Çok fazla detaylı bilgi var. Sonraki belge incelemesi için de buraya gelebilirsiniz.

Burada sadece adresini kopyalamanız ve ardından daha önce oluşturulan projede go get komutunu kullanmanız yeterlidir. Komut şu şekildedir
$ go get github.com/gin-gonic/ginSüreçte birçok bağımlılık indirilecektir. Hata yoksa indirme başarılı demektir.
$ go get github.com/gin-gonic/gin
go: added github.com/bytedance/sonic v1.8.0
go: added github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311
go: added github.com/gin-contrib/sse v0.1.0
go: added github.com/gin-gonic/gin v1.9.0
go: added github.com/go-playground/locales v0.14.1
go: added github.com/go-playground/universal-translator v0.18.1
go: added github.com/go-playground/validator/v10 v10.11.2
go: added github.com/goccy/go-json v0.10.0
go: added github.com/json-iterator/go v1.1.12
go: added github.com/klauspost/cpuid/v2 v2.0.9
go: added github.com/leodido/go-urn v1.2.1
go: added github.com/mattn/go-isatty v0.0.17
go: added github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421
go: added github.com/modern-go/reflect2 v1.0.2
go: added github.com/pelletier/go-toml/v2 v2.0.6
go: added github.com/twitchyliquid64/golang-asm v0.15.1
go: added github.com/ugorji/go/codec v1.2.9
go: added golang.org/x/arch v0.0.0-20210923205945-b76863e36670
go: added golang.org/x/crypto v0.5.0
go: added golang.org/x/net v0.7.0
go: added golang.org/x/sys v0.5.0
go: added golang.org/x/text v0.7.0
go: added google.golang.org/protobuf v1.28.1
go: added gopkg.in/yaml.v3 v3.0.1Tamamlandıktan sonra go.mod dosyasını kontrol edin
$ cat go.mod
module golearn
go 1.20
require github.com/gin-gonic/gin v1.9.0
require (
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.11.2 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)Öncekiyle karşılaştırıldığında çok fazla şey eklendiğini görebilirsiniz. Aynı zamanda go.sum adında bir dosyanın dizinde bulunduğunu fark edeceksiniz
$ ls
go.mod go.sum main.goBurada önce durdurun, main.go dosyasını aşağıdaki kodla değiştirin:
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
gin.Default().Run()
}Projeyi tekrar çalıştırın
$ go run golearn
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080Böylece tek satır kodla en basit Web sunucusunu çalıştırdınız. Artık bir bağımlılığa ihtiyaç duymadığınızda, bağımlılığı silmek için go get komutunu da kullanabilirsiniz. Burada Gin'i silme örneği olarak alalım
$ go get github.com/gin-gonic/gin@none
go: removed github.com/gin-gonic/gin v1.9.0Bağımlılık adresinin arkasına @none ekleyerek bu bağımlılığı silebilirsiniz. Sonuç da silmenin başarılı olduğunu gösterir. Bu zamanda go.mod dosyasını tekrar kontrol ettiğinizde Gin bağımlılığının olmadığını göreceksiniz.
$ cat go.mod | grep github.com/gin-gonic/ginEn son sürüme yükseltmek istediğinizde, @latest son eki ekleyebilirsiniz. Veya kullanılabilir Release sürüm numarasını kendiniz sorgulayabilirsiniz
$ go get -u github.com/gin-gonic/gin@latestKomut Satırı Yükleme
go install komutu üçüncü taraf bağımlılığı yerel makineye indirir ve ikili dosyaya derler. Go'nun derleme hızı sayesinde, bu süreç genellikle çok zaman almaz. Ardından go bunu $GOPATH/bin veya $GOBIN dizinine koyar. Böylece küresel olarak bu ikili dosyayı çalıştırabilirsiniz (bu yolları ortam değişkenlerine eklediyseniz).
::: ipucu
install komutunu kullanırken, sürüm numarası belirtilmelidir.
:::
Örneğin Go dili ile yazılmış hata ayıklayıcı delve'yi indirin
$ go install github.com/go-delve/delve/cmd/dlv@latest
go: downloading github.com/go-delve/delve v1.22.1
go: downloading github.com/cosiner/argv v0.1.0
go: downloading github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d
go: downloading github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62
go: downloading github.com/google/go-dap v0.11.0
go: downloading github.com/hashicorp/golang-lru v1.0.2
go: downloading golang.org/x/arch v0.6.0
go: downloading github.com/cpuguy83/go-md2man/v2 v2.0.2
go: downloading go.starlark.net v0.0.0-20231101134539-556fd59b42f6
go: downloading github.com/cilium/ebpf v0.11.0
go: downloading github.com/mattn/go-runewidth v0.0.13
go: downloading github.com/russross/blackfriday/v2 v2.1.0
go: downloading github.com/rivo/uniseg v0.2.0
go: downloading golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2
$ dlv -v
Error: unknown shorthand flag: 'v' in -v
Usage:
dlv [command]
Available Commands:
attach Attach to running process and begin debugging.
completion Generate the autocompletion script for the specified shell
connect Connect to a headless debug server with a terminal client.
core Examine a core dump.
dap Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
debug Compile and begin debugging main package in current directory, or the package specified.
exec Execute a precompiled binary, and begin a debug session.
help Help about any command
test Compile test binary and begin debugging program.
trace Compile and begin tracing program.
version Prints version.
Additional help topics:
dlv backend Help about the --backend flag.
dlv log Help about logging flags.
dlv redirect Help about file redirection.
Use "dlv [command] --help" for more information about a command.Modül Yönetimi
Yukarıdaki tüm içerikler sadece Go Mod'un temel kullanımını anlatıyor. Ancak Go Mod'u öğrenmek için sadece bunlar kesinlikle yeterli değil. Resmi modül tanımı: sürümlü paketler kümesidir. Yukarıdaki tanımda, paket zaten tanıdık bir kavram olmalıdır. Sürüm ise semantik sürüm numarasına uymalıdır. Tanım: v(major).(minor).(patch) formatıdır. Örneğin Go sürümü v1.20.1, ana sürüm 1, küçük sürüm 20, yama sürümü 1, birlikte v1.20.1'dir. Aşağıda daha detaylı bir açıklama var:
major: major sürümü değiştiğinde, projenin uyumsuz değişiklikler yaptığını gösterir. Eski sürüm proje yeni sürüme yükseltildiğinde büyük olasılıkla normal çalışamaz.minor:minorsürümü değiştiğinde, projenin yeni özellikler eklediğini gösterir. Sadece önceki sürümün temelinde yeni işlevler eklenir.patch:patchsürümü değiştiğinde, sadece düzeltilen hata olduğunu gösterir. Yeni işlev eklenmez.
Yaygın Komutlar
| Komut | Açıklama |
|---|---|
go mod download | Mevcut projenin bağımlılık paketlerini indirir |
go mod edit | go.mod dosyasını düzenler |
go mod graph | Modül bağımlılık grafiğini çıktılar |
go mod init | Mevcut dizinde go mod başlatır |
go mod tidy | Proje modüllerini temizler |
go mod verify | Projenin bağımlılık yasallığını doğrular |
go mod why | Projenin hangi yerlerde bağımlılık kullandığını açıklar |
go clean -modcache | Proje modül bağımlılık önbelleğini silmek için kullanılır |
go list -m | Modülleri listeler |
Komutlar hakkında daha fazla bilgi için go mod cmd adresine gidin
Modül Depolama
Go Mod ile proje yönetimi yaparken, modül önbelleği varsayılan olarak $GOPATH/pkg/mod dizininde saklanır. $GOMODCACHE'i değiştirerek başka bir konumda saklanmasını da belirtebilirsiniz.
$ go env -w GOMODCACHE=modül önbellek yolunuzAynı makinedeki tüm Go Module projeleri bu dizindeki önbelleği paylaşır. Önbelleğin boyut sınırı yoktur ve otomatik olarak silinmez. Önbellekte açılan bağımlılık kaynak dosyaları salt okunurdur. Önbelleği temizlemek istiyorsanız aşağıdaki komutu çalıştırabilirsiniz.
$ go clean -modcache$GOMODCACHE/cache/download dizininde bağımlılığın orijinal dosyaları saklanır. Hash dosyaları, orijinal sıkıştırılmış paketler vb. dahil. Aşağıdaki örnek:
$ ls $(go env GOMODCACHE)/cache/download/github.com/246859/hello/@v -1
list
v1.0.0.info
v1.0.0.lock
v1.0.0.mod
v1.0.0.zip
v1.0.0.ziphashAçılan bağımlılığın organizasyon formu aşağıda gösterildiği gibidir. Belirtilen modülün kaynak kodudur.
$ ls $(go env GOMODCACHE)/github.com/246859/hello@v1.0.0 -1
LICENSE
README.md
cmd/
example/
go.mod
hello.go
hello_test.goSürüm Seçimi
Go bağımlılık sürümü seçerken, minimum sürüm seçim ilkesini izler. Aşağıda resmi web sitesinden bir örnek var. Ana modül modül A'nın 1.2 sürümünü ve modül B'nin 1.2 sürümünü referans alır. Aynı zamanda modül A'nın 1.2 sürümü modül C'nin 1.3 sürümünü referans alır. Modül B'nin 1.2 sürümü modül C'nin 1.4 sürümünü referans alır. Ve modül C'nin 1.3 ve 1.4 sürümleri aynı anda modül D'nin 1.2 sürümünü referans alır. Minimum kullanılabilir sürüm ilkesine göre, Go sonunda A1.2, B1.2, C1.4 ve D1.2 sürümlerini seçer. İçinde açık mavi go.mod dosyasının yüklenenlerini gösterir, çerçevelenen son seçilen sürümleri gösterir.
Resmi web sitesinde diğer birkaç örnek verilmiştir. Genel anlamı neredeyse aynıdır.
go.mod
Her Go Mod projesi oluşturulduğunda bir go.mod dosyası oluşturulur. Bu nedenle go.mod dosyasına aşina olmak çok gereklidir. Ancak çoğu durumda go.mod dosyasını manuel olarak değiştirmeye gerek yoktur.
module golearn
go 1.20
require github.com/gin-gonic/gin v1.9.0
require (
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.11.2 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)Dosyada çoğu bağımlılık adresinin github gibi ifadeler içerdiğini bulabilirsiniz. Bunun nedeni Go'nun ortak bir bağımlılık deposunun olmamasıdır. Çoğu açık kaynak proje Gitub'da barındırılır. Bazıları da kendi kendine depo oluşturur. Örneğin google.golang.org/protobuf, golang.org/x/crypto. Normalde, bu URL dizisi aynı zamanda Go projesinin modül adıdır. Bu bir sorun oluşturur. URL büyük/küçük harf duyarlı değildir. Ancak bağımlılığı saklayan klasör büyük/küçük harf duyarlıdır. Bu nedenle go get github.com/gin-gonic/gin ve go get github.com/gin-gonic/Gin aynı bağımlılığa referans verir ancak yerel saklama yolu farklıdır. Bu durum发生时,Go doğrudan büyük harfleri saklama yolu olarak almaz. Bunun yerine !küçük harf olarak kaçış yapar. Örneğin github.com\BurntSushi sonunda github.com\!burnt!sushi olarak kaçış yapar.
module
module anahtar kelimesi mevcut projenin modül adını bildirir. Bir go.mod dosyasında sadece bir module anahtar kelimesi görünebilir. Örnekte
module golearnMevcut modül adının golearn olduğunu gösterir. Örneğin Gin bağımlılığının go.mod dosyasını açtığınızda module adını bulabilirsiniz
module github.com/gin-gonic/ginGin'in modül adı bağımlılık indirirken kullanılan adrestir. Bu genellikle modül adı formatıdır. domain/kullanıcı/depo adı.
::: ipucu
Dikkat edilmesi gereken bir nokta, ana sürüm 1'den büyük olduğunda, ana sürüm numarasının modül adında yansıtılması gerektiğidir. Örneğin
github.com/my/exampleEğer sürüm v2.0.0'a yükseltilirse, modül adı aşağıdaki gibi değiştirilmelidir
github.com/my/example/v2Eğer orijinal proje eski sürümü referans alıyorsa ve yeni sürüm ayırt edilmezse, bağımlılık referans alındığında yol tutarlı olduğundan, kullanıcı ana sürüm değişikliğinin getirdiği uyumsuz değişiklikleri ayırt edemez. Bu şekilde program hatası oluşabilir.
:::
Deprecation
module'ün önceki satırının başında Deprecated yorumu ile bu modülün kullanımdan kaldırıldığını belirtin. Örneğin
// Deprecated: use example.com/mod/v2 instead.
module example.com/modgo
go anahtar kelimesi mevcut projeyi yazmak için kullanılan Go sürümünü gösterir. Sürüm numarası semantik kurallara uymalıdır. Go sürümüne göre, Go Mod farklı davranışlar sergiler. Aşağıda basit bir örnek var. Go'nun kullanılabilir sürümleri için resmi web sitesine gidin.
go 1.20require
require anahtar kelimesi bir dış bağımlılık referans alındığını gösterir. Örneğin
require github.com/gin-gonic/gin v1.9.0Format require modül adı sürüm numarası'dır. Birden fazla referans olduğunda parantez ile çevrilebilir
require (
github.com/bytedance/sonic v1.8.0 // indirect
)// indirect yorumu ile işaretlenen bağımlılığın mevcut proje tarafından doğrudan referans alınmadığını gösterir. Projenin doğrudan referans aldığı bağımlılık bu bağımlılığı referans almış olabilir. Bu nedenle mevcut proje için dolaylı referanstır. Ana tahta değiştiğinde modül adında yansıtılması gerektiğinden bahsedilmişti. Bu kurala uymayan modüller standart dışı modül olarak adlandırılır. require时,incompatible yorumu eklenir.
require example.com/m v4.1.2+incompatibleSahte Sürüm
Yukarıdaki go.mod dosyasında, bazı bağımlılık paketlerinin sürümünün semantik sürüm numarası olmadığını, bir dizi bilinmeyen string olduğunu bulabilirsiniz. Bu aslında ilgili sürümün CommitID'sidir. Semantik sürüm genellikle belirli bir Release'ı ifade eder. Sahte sürüm numarası ise belirli bir Commit'u belirtebilir. Genellikle format vx.y.z-yyyyMMddHHmmss-CommitId'dir. vx.y.z mutlaka gerçek olmadığı için, sahte sürüm olarak adlandırılır. Aşağıdaki örnekte v0.0.0 mevcut değildir. Gerçekten geçerli olan sonraki 12 basamaklı CommitID'dir.
// CommitID genellikle ilk 12 basamağı alır
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirectAynı şekilde, bağımlılık indirirken semantik sürüm numarasını değiştirmek için CommitID belirtebilirsiniz
go get github.com/chenzhuoyu/base64x@fe3a3abad311exclude
exclude anahtar kelimesi bağımlılığın belirtilen sürümünün yüklenmemesini gösterir. Aynı zamanda require aynı sürümü referans alırsa, yok sayılır. Bu anahtar kelime sadece ana modülde etkilidir. Örneğin
exclude golang.org/x/net v1.2.3
exclude (
golang.org/x/crypto v1.4.5
golang.org/x/text v1.6.7
)replace
replace belirtilen sürümün bağımlılığını değiştirir. Modül yolu ve sürümü ile veya diğer platform belirtilen dosya yolu ile değiştirilebilir. Örnek
replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
replace (
golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
golang.org/x/net => example.com/fork/net v1.4.5
golang.org/x/net v1.2.3 => ./fork/net
golang.org/x/net => ./fork/net
)Sadece => solundaki sürüm değiştirilir. Diğer sürümler aynı bağımlılığa normal şekilde erişebilir. Yerel yol veya modül yolu belirtilen değiştirme kullanılsın, değiştirme modülünün go.mod dosyası varsa, module talimatı değiştirilen modül yolu ile eşleşmelidir.
retract
retract talimatı, retract tarafından belirtilen sürüm veya sürüm aralığının bağımlılık olmaması gerektiğini gösterir. Örneğin yeni bir sürüm yayınlandıktan sonra ciddi bir sorun bulunduğunda, bu zamanda retract talimatı kullanılabilir.
Bazı sürümleri geri çek
retract (
v1.0.0 // Published accidentally.
v1.0.1 // Contains retractions only.
)Sürüm aralığını geri çek
retract v1.0.0
retract [v1.0.0, v1.9.9]
retract (
v1.0.0
[v1.0.0, v1.9.9]
)go.sum
go.sum dosyası proje başlangıcında mevcut değildir. Sadece gerçekten dış bağımlılık referans alındıktan sonra oluşturulur. go.sum dosyası insan okuması için uygun değildir. Bu dosyayı manuel olarak değiştirmeniz de önerilmez. İşlevi öncelikle tutarlı oluşturma sorununu çözmektir. Yani farklı kişiler farklı ortamlarda aynı projeyi oluştururken referans alınan bağımlılık paketleri tamamen aynı olmalıdır. Bu sadece bir go.mod dosyası ile garanti edilemez.
Sonraki bir bağımlılık indirirken, Go'nun baştan sona ne yaptığını görelim. Önce aşağıdaki komutla bir bağımlılık indirin
go get github.com/bytedance/sonic v1.8.0go get komutu önce bağımlılık paketini yerel önbellek dizinine indirir. Genellikle bu dizin $GOMODCACHE/cache/download/'dır. Bu dizin alan adına göre farklı web sitelerinin bağımlılık paketlerini ayırır. Bu nedenle aşağıdaki dizin yapısını görebilirsiniz
$ ls
cloud.google.com/ go.opencensus.io/ gopkg.in/ nhooyr.io/
dmitri.shuralyov.com/ go.opentelemetry.io/ gorm.io/ rsc.io/
github.com/ go.uber.org/ honnef.co/ sumdb/
go.etcd.io/ golang.org/ lukechampine.com/
go.mongodb.org/ google.golang.org/ modernc.org/Yukarıdaki örnekte indirilen bağımlılık paketi şu yolda saklanır
$GOMODCACHE/cache/download/github.com/bytedance/sonic/@v/Olası dizin yapısı aşağıdaki gibidir. Birkaç sürüm adlı dosya olacaktır
$ ls
list v1.8.0.lock v1.8.0.ziphash v1.8.3.mod
v1.5.0.mod v1.8.0.mod v1.8.3.info v1.8.3.zip
v1.8.0.info v1.8.0.zip v1.8.3.lock v1.8.3.ziphashNormalde, bu dizinde mutlaka bir list dosyası vardır. İlgili bağımlılığın bilinen sürüm numaralarını kaydeder. Her sürüm için, aşağıdaki dosyalar olacaktır:
zip: Bağımlılığın kaynak kodu sıkıştırılmış paketiziphash: Bağımlılık sıkıştırma paketine göre hesaplanan hash değeriinfo: json formatında sürüm meta verisimod: Bu sürümüngo.moddosyasılock: Geçici dosya, resmi ne işe yaradığını söylemedi
Genellikle, Go sıkıştırma paketi ve go.mod iki dosyanın hash değerini hesaplar. Ardından GOSUMDB tarafından belirtilen sunucuda (varsayılan sum.golang.org) bu bağımlılık paketinin hash değerini sorgular. Yerel hesaplanan hash değeri sorgulanan sonuçla tutarsızsa, daha fazla yürütme olmaz. Tutarlıysa, go.mod dosyasını günceller ve go.sum dosyasına iki kayıt ekler.大致 olarak şu şekildedir:
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=::: ipucu
Eğer GOSUMDB devre dışı bırakılırsa, Go doğrudan yerel hesaplanan hash değerini go.sum dosyasına yazar. Genellikle bunu yapmanız önerilmez.
:::
Normalde her bağımlılığın iki kaydı vardır. İlki sıkıştırma paketinin hash değeri, ikincisi bağımlılık paketinin go.mod dosyasının hash değeridir. Kayıt formatı modül adı sürüm numarası algoritma adı:hash değeri'dir. Bazı eski bağımlılık paketlerinde go.mod dosyası olmayabilir. Bu nedenle ikinci hash kaydı olmaz. Bu proje başka bir kişinin ortamında oluşturulduğunda, Go go.mod'da belirtilen yerel bağımlılığa göre hash değerini hesaplar. Ardından go.sum'da kaydedilen hash değeri ile karşılaştırır. Hash değeri tutarsızsa, bağımlılık sürümünün farklı olduğu anlamına gelir. Oluşturma reddedilir. Bu durum发生时,yerel bağımlılık ve go.sum dosyası değiştirilmiş olabilir. Ancak go.sum GOSUMDB sorgu kaydı olduğundan, go.sum dosyasına daha çok inanma eğilimindedir.
Özel Modül
Go Mod çoğu araç açık kaynak projeler için söylenir. Ancak Go özel modülleri de destekler. Özel projeler için, genellikle modül özel işlemi için aşağıdaki ortam yapılandırmalarını yapılandırmak gerekir
GOPROXY: Bağımlılığın proxy sunucu koleksiyonuGOPRIVATE: Özel modül modül yolu öneklerinin genel mod listesi. Modül adı kurallara uyuyorsa, bu modül özel modül olarak gösterilir. Spesifik davranış GONOPROXY ve GONOSUMDB ile aynıdır.GONOPROXY: Proxy'den indirilmeyen modül yolu öneklerinin genel mod listesi. Kurallara uyuyorsa modül indirirken GOPROXY kullanılmaz. Doğrudan sürüm kontrol sisteminden indirmeye çalışılır.GONOSUMDB: GOSUMDB genel doğrulaması yapılmayan modül yolu öneklerinin genel mod listesi. Kurallara uyuyorsa modül indirirken doğrulama checksum'un genel veritabanından geçmez.GOINSECURE: HTTP ve diğer güvensiz protokoller aracılığıyla alınabilen modül yolu öneklerinin genel mod listesi.
Çalışma Alanı
Önce go.mod dosyasının replace talimatını desteklediğinden bahsetmiştik. Bu, henüz yayınlanamayan yerel değişiklikleri geçici olarak kullanmamızı sağlar. Aşağıda gösterildiği gibi
replace (
github.com/246859/hello v1.0.1 => ./hello
)Derleme sırasında, go yerel hello modülünü kullanır. Gelecekte yeni sürüm yayınlandıktan sonra kaldırın.
Ancak replace talimatı kullanılırsa, go.mod dosyasının içeriği değiştirilir. Ve bu değişiklik yanlışlıkla uzak depoya gönderilebilir. Bu görmek istemediğimiz bir durumdur. Çünkü replace talimatı tarafından belirtilen target bir dosya yoludur, ağ URL'si değildir. Bu makinede kullanılabilen yol başka bir makinede kullanılamayabilir. Dosya yolu çapraz platform açısından da büyük bir sorundur. Bu tür sorunları çözmek için, çalışma alanı ortaya çıktı.
Çalışma alanı (workspace), Go'nun 1.18'de tanıttığı çoklu modül yönetimi için yeni bir çözümdür. Yerel çoklu modül geliştirme çalışmasını daha iyi yapmak amaçlanmıştır. Aşağıda bir örnek ile anlatılacaktır.
Örnek depo: 246859/work: go work example (github.com)
Örnek
Önce proje altında iki bağımsız go modül var. Sırasıyla auth, user
$ ls -1
LICENSE
README.md
auth
go.work
userauth modülü user modülünün User yapısına bağımlıdır. İçerik şu şekildedir
package auth
import (
"errors"
"github.com/246859/work/user"
)
// Verify user credentials if is ok
func Verify(user user.User) (bool, error) {
password, err := query(user.Name)
if err != nil {
return false, err
}
if password != user.Password {
return false, errors.New("authentication failed")
}
return true, nil
}
func query(username string) (string, error) {
if username == "jack" {
return "jack123456", nil
}
return "", errors.New("user not found")
}user modül içeriği şu şekildedir
package user
type User struct {
Name string
Password string
Age int
}Bu projede, go.work dosyasını şu şekilde yazabiliriz
go 1.22
use (
./auth
./user
)İçeriği çok kolay anlaşılır. use talimatı kullanılarak hangi modüllerin derlemeye katılacağı belirtilir. Sonraki auth modülündeki kodu çalıştırın
// auth/example/main.go
package main
import (
"fmt"
"github.com/246859/work/auth"
"github.com/246859/work/user"
)
func main() {
ok, err := auth.Verify(user.User{Name: "jack", Password: "jack123456"})
if err != nil {
panic(err)
}
fmt.Printf("%v", ok)
}Aşağıdaki komutu çalıştırın. Sonuçtan modülün başarıyla import edildiğini öğrenin.
$ go run ./auth/example
trueÖnceki sürümlerde, bu iki bağımsız modül için, auth modülü user modülündeki kodu kullanmak istiyorsa sadece iki yol vardı
- user modülünün değişikliklerini gönderin ve uzak depoya itin. Yeni sürüm yayınlayın. Ardından
go.moddosyasını belirtilen sürüme değiştirin go.moddosyasını değiştirin, bağımlılığı yerel dosyaya yönlendirin
İki yöntem de go.mod dosyasını değiştirmeyi gerektirir. Çalışma alanının varlığı, go.mod dosyasını değiştirmeden diğer modülleri import etmeyi mümkün kılar. Ancak anlaşılması gereken bir nokta, go.work dosyası sadece geliştirme sürecinde kullanılır. Varlığı sadece yerel geliştirmeyi daha uygun yapmak içindir. Bağımlılık yönetimi için değil. Sadece geçici olarak gönderme ve yayınlama sürecini atlamanızı sağlar. user modülünün yeni değişikliklerini hemen kullanmanızı sağlar. Beklemenize gerek yoktur. user modülü test edildikten sonra, sonunda yeni sürüm yayınlanmalıdır. Ve auth modülü sonunda go.mod dosyasını değiştirmeli ve en son sürümü referans almalıdır (bu süreç go work sync komutu ile tamamlanabilir). Bu nedenle normal go geliştirme sürecinde, go.work VCS'ye gönderilmemelidir (örnek depodaki go.work sadece gösterim içindir). Çünkü içeriği yerel dosyalara bağlıdır. Ve işlevi de sadece yerel geliştirme ile sınırlıdır.
Komutlar
Aşağıda bazı çalışma alanı komutları var
| Komut | Tanıtım |
|---|---|
| edit | go.work'ü düzenler |
| init | Yeni bir çalışma alanı başlatır |
| sync | Çalışma alanının modül bağımlılıklarını senkronize eder |
| use | go.work'e yeni bir modül ekler |
| vendor | Bağımlılıkları vendor formatında kopyalar |
Komutlar hakkında daha fazla bilgi için go work cmd adresine gidin
Talimatlar
go.work dosyasının içeriği çok basittir. Sadece üç talimat var
go, go sürümünü belirtiruse, kullanılan modülleri belirtirreplace, değiştirilen modülleri belirtir
use talimatı dışında, diğer ikisi temelde go.mod'daki talimatlara eşdeğerdir. Sadece go.work'teki replace talimatı tüm modüller üzerinde etkili olur. Tam bir go.work aşağıda gösterildiği gibidir.
go 1.22
use(
./auth
./user
)
repalce github.com/246859/hello v1.0.0 => /home/jack/code/hello