Modul
Setiap bahasa modern memiliki tool manajemen dependensi yang matang, seperti Gradle untuk Java, Pip untuk Python, Npm untuk NodeJs, dll. Tool manajemen dependensi yang baik dapat menghemat banyak waktu bagi developer dan meningkatkan efisiensi pengembangan. Namun Go di awal tidak memiliki solusi manajemen dependensi yang matang, saat itu semua kode disimpan di direktori GOPATH, sangat tidak ramah untuk proyek engineering, versi kacau, dependensi sulit dikelola. Untuk menyelesaikan masalah ini, developer komunitas besar berdebat, situasi sempat kacau,期间 juga muncul beberapa yang unggul seperti Vendor, sampai Go1.11官方 akhirnya meluncurkan tool manajemen dependensi官方 Go Mod, mengakhiri situasi kacau sebelumnya, dan terus disempurnakan di update berikutnya, mengeliminasi tool lama. Hingga kini, saat menulis artikel ini, versi rilis Go sudah mencapai 1.20, hari ini hampir semua proyek Go mengadopsi Go Mod, oleh karena itu artikel ini hanya akan memperkenalkan Go Mod,官方 juga menulis dokumentasi yang sangat detail untuk modul Go: Go Modules Reference.
Menulis Modul
Go Module pada dasarnya berbasis VCS (Version Control System), saat Anda mendownload dependensi, sebenarnya mengeksekusi command VCS, seperti git. Jadi jika ingin membagikan library yang Anda tulis, hanya perlu memenuhi tiga hal berikut:
- Repository source code dapat diakses publik, dan VCS termasuk salah satu berikut:
- git
- hg (Mercurial)
- bzr (Bazaar)
- svn
- fossil
- Adalah proyek go mod yang sesuai spesifikasi
- Sesuai dengan spesifikasi semantic versioning
Jadi Anda hanya perlu normal mengembangkan menggunakan VCS, dan memberi tag versi spesifik Anda dengan Tag yang sesuai standar, orang lain dapat mendownload library yang Anda tulis melalui nama modul. Berikut akan mendemonstrasikan beberapa langkah pengembangan modul melalui contoh.
Repository contoh: 246859/hello: say hello (github.com)
Persiapan
Sebelum memulai pastikan versi Anda cukup untuk sepenuhnya mendukung go mod (go >= 1.17), dan mengaktifkan Go Module, lihat apakah sudah aktif melalui command berikut
$ go env GO111MODULEJika belum aktif, aktifkan Go Module melalui command berikut
$ go env -w GO111MODULE=onMembuat
Pertama Anda perlu repository source code yang dapat diakses publik, ada banyak pilihan, saya cukup merekomendasikan Github. Buat proyek baru di sana, beri nama hello, nama repository meskipun tidak ada batasan khusus, tetapi disarankan tidak menggunakan karakter spesial, karena ini akan mempengaruhi nama modul.

Setelah selesai membuat, dapat dilihat URL repository adalah https://github.com/246859/hello, nama modul Go yang sesuai adalah github.com/246859/hello.

Lalu clone ke lokal, inisialisasi modul melalui command go mod init.
$ 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/helloMenulis
Lalu dapat melakukan pengembangan, fungsinya sangat sederhana, hanya satu fungsi
// 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)
}Sekaligus tulis file tes untuk unit test
// 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)
}
}Selanjutnya tulis program command line untuk output hello, fungsinya juga sangat sederhana. Untuk program command line, sesuai norma dibuat di cmd/app_name/ proyek, jadi file program command line hello disimpan di direktori cmd/hello/, lalu tulis kode terkait di dalamnya.
// 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())
}
}Testing
Setelah menulis selesai, format source code dan test
$ go fmt && go vet ./...
$ go test -v .
=== RUN TestHello
--- PASS: TestHello (0.00s)
PASS
ok github.com/246859/hello 0.023sJalankan program command line
$ go run ./cmd/hello -name jack
hello jack!Dokumentasi
Terakhir, perlu menulis README yang ringkas dan jelas untuk library ini, agar developer lain sekilas tahu cara menggunakannya
# 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)
}
```Ini adalah dokumen README yang sangat sederhana, Anda juga dapat memperkayanya sendiri.
Upload
Setelah semua kode ditulis dan test selesai, dapat submit dan push modifikasi ke repository remote.
$ 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(-)Total enam commit tidak banyak, setelah submit buat tag untuk commit terbaru
$ 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 commitTerakhir push ke repository remote
$ 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.0Setelah push selesai, buat release untuk itu (ada tag sudah cukup, release hanya sesuai norma github)

Dengan demikian, penulisan modul selesai, di atas adalah proses dasar pengembangan modul, developer lain dapat mengimport kode atau menginstal tool command line melalui nama modul.
Mengimport
Referensi library melalui go get
$ go get github.com/246859/hello@latest
go: downloading github.com/246859/hello v1.0.0
go: added github.com/246859/hello v1.0.0Instal program command line melalui go install
$ go install github.com/246859/hello/cmd/hello@latest && hello -name jack
hello jack!Atau langsung jalankan menggunakan go run
$ go run -mod=mod github.com/246859/hello/cmd/hello -name jack
hello jack!Setelah library direferensikan, Go Package akan membuat halaman khusus untuknya, proses ini otomatis, developer tidak perlu melakukan pekerjaan apa pun, misalnya library hello memiliki halaman dokumentasi eksklusif, seperti ditunjukkan di bawah ini.

Untuk informasi lebih detail tentang upload modul,前往 Add a package.
Untuk informasi tentang cara menghapus informasi modul,前往 Removing a package.
Mengatur Proxy
Go meskipun tidak memiliki central repository seperti Maven Repo, PyPi, NPM, tetapi memiliki proxy repository官方: Go modules services (golang.org), ia akan meng-cache modul yang didownload developer sesuai versi dan nama modul. Namun karena servernya deployed di luar negeri, kecepatan akses tidak ramah bagi user domestik, oleh karena itu perlu memodifikasi alamat proxy modul default, saat ini di domestik yang cukup baik ada beberapa berikut:

Di sini memilih proxy Qiniu Cloud, jalankan command berikut untuk memodifikasi proxy Go,其中 direct表示 setelah proxy download gagal bypass cache proxy langsung akses repository source code.
$ go env -w GOPROXY=https://goproxy.cn,directSetelah proxy berhasil dimodifikasi, di masa depan mendownload dependensi akan sangat cepat.
Mendownload Dependensi
Setelah memodifikasi proxy, selanjutnya coba instal dependensi third-party,官方 Go memiliki website query dependensi khusus: Go Packages.
Referensi Kode
Cari framework Web terkenal Gin di dalamnya.

Di sini akan muncul banyak hasil pencarian, saat menggunakan dependensi third-party, perlu mempertimbangkan apakah mengadopsi dependensi ini berdasarkan jumlah referensi dan waktu update, di sini langsung pilih yang pertama

Setelah masuk halaman yang sesuai, dapat dilihat ini adalah halaman dokumentasi dependensi ini, ada sangat banyak informasi detail tentangnya, saat membaca dokumentasi berikutnya juga dapat ke sini.

Di sini hanya perlu copy alamatnya, lalu di proyek yang dibuat sebelumnya gunakan command go get, command sebagai berikut
$ go get github.com/gin-gonic/ginProsesnya akan mendownload banyak dependensi, selama tidak error berarti download berhasil.
$ 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.1Setelah selesai lihat file go.mod
$ 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
)Dapat dilihat dibanding sebelumnya banyak hal, sekaligus akan menemukan ada file bernama go.sum di direktori
$ ls
go.mod go.sum main.goDi sini暂时 tidak dibahas, modifikasi file main.go menjadi kode berikut:
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
gin.Default().Run()
}Jalankan proyek lagi
$ 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 :8080Dengan demikian, melalui satu baris kode menjalankan web server paling sederhana. Saat tidak lagi membutuhkan dependensi tertentu, juga dapat menggunakan command go get untuk menghapus dependensi tersebut, di sini dengan menghapus Gin sebagai contoh
$ go get github.com/gin-gonic/gin@none
go: removed github.com/gin-gonic/gin v1.9.0Tambahkan @none di belakang alamat dependensi dapat menghapus dependensi tersebut, hasil juga memberitahu berhasil menghapus, saat ini lihat file go.mod lagi akan发现 tidak ada dependensi Gin.
$ cat go.mod | grep github.com/gin-gonic/ginSaat perlu upgrade ke versi terbaru, dapat menambahkan suffix @latest, atau dapat自行 query nomor versi Release yang tersedia
$ go get -u github.com/gin-gonic/gin@latestInstal Command Line
Command go install akan mendownload dependensi third-party ke lokal dan kompilasi menjadi file binary, berkat kecepatan kompilasi go, proses ini biasanya tidak memakan banyak waktu, lalu go akan menyimpannya di direktori $GOPATH/bin atau $GOBIN, agar dapat mengeksekusi file binary tersebut secara global (prasyarat Anda menambahkan path ini ke environment variable).
TIP
Saat menggunakan command install, harus menentukan nomor versi.
Misalnya mendownload debugger delve yang ditulis dalam bahasa go
$ 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.Manajemen Modul
Semua konten di atas hanya讲述 penggunaan dasar Go Mod, tetapi sebenarnya untuk mempelajari Go Mod hanya ini sama sekali tidak cukup.官方 mendefinisikan modul sebagai: sekumpulan paket yang ditandai versi. Definisi di atas, paket seharusnya konsep yang sangat familiar, sedangkan versi harus mengikuti semantic versioning, didefinisikan sebagai: format v(major).(minor).(patch), misalnya versi Go v1.20.1, major version adalah 1, minor version adalah 20, patch version adalah 1, digabungkan menjadi v1.20.1, berikut adalah penjelasan lebih detail:
major: Saat major version berubah,说明 proyek terjadi perubahan yang tidak kompatibel, proyek versi lama upgrade ke versi baru kemungkinan besar tidak dapat berjalan normal.minor: Saatminorversion berubah,说明 proyek menambahkan fitur baru, hanya menambahkan fitur baru di basis versi sebelumnya.patch: Saatpatchversion berubah,说明 hanya ada bug yang diperbaiki, tidak menambahkan fitur baru apa pun.
Command Umum
| Command | Penjelasan |
|---|---|
go mod download | Mendownload dependensi paket proyek saat ini |
go mod edit | Mengedit file go.mod |
go mod graph | Output grafik dependensi modul |
go mod init | Inisialisasi go mod di direktori saat ini |
go mod tidy | Membersihkan modul proyek |
go mod verify | Memverifikasi legalitas dependensi proyek |
go mod why | Menjelaskan di mana proyek menggunakan dependensi |
go clean -modcache | Digunakan untuk menghapus cache dependensi modul proyek |
go list -m | Mendaftarkan modul |
前往 go mod cmd了解更多 informasi terkait command
Penyimpanan Modul
Saat menggunakan Go Mod untuk manajemen proyek, cache modul default disimpan di direktori $GOPATH/pkg/mod, juga dapat memodifikasi $GOMODCACHE untuk menentukan disimpan di lokasi lain.
$ go env -w GOMODCACHE=path cache modul AndaSemua proyek Go Module di mesin yang sama berbagi cache di direktori ini, cache tidak ada batasan ukuran dan tidak akan otomatis dihapus, source code dependensi yang di-extract di cache adalah read-only, ingin mengosongkan cache dapat jalankan command berikut.
$ go clean -modcacheDi direktori $GOMODCACHE/cache/download menyimpan file asli dependensi, termasuk file hash, compressed package asli, dll, contoh berikut:
$ 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.ziphashStruktur organisasi dependensi yang di-extract sebagai berikut, adalah source code modul yang ditentukan.
$ ls $(go env GOMODCACHE)/github.com/246859/hello@v1.0.0 -1
LICENSE
README.md
cmd/
example/
go.mod
hello.go
hello_test.goPemilihan Versi
Go saat pemilihan versi dependensi, mengikuti prinsip pemilihan versi minimal. Berikut adalah contoh dari官网, modul utama mereferensikan versi 1.2 modul A dan versi 1.2 modul B, sekaligus versi 1.2 modul A mereferensikan versi 1.3 modul C, versi 1.2 modul B mereferensikan versi 1.4 modul C, dan versi 1.3 dan 1.4 modul C keduanya mereferensikan versi 1.2 modul D, menurut prinsip versi tersedia minimal, Go akhirnya akan memilih versi A1.2, B1.2, C1.4 dan D1.2.其中 biru muda表示 file go.mod yang dimuat, yang dibingkai表示 versi yang akhirnya dipilih.
官网 juga memberikan beberapa contoh lainnya, artinya hampir sama.
go.mod
Setiap membuat proyek Go Mod akan menghasilkan file go.mod, oleh karena itu familiar dengan file go.mod sangat perlu, tetapi sebagian besar kasus tidak perlu memodifikasi file go.mod secara manual.
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
)Di file dapat发现 sebagian besar alamat dependensi带有 kata seperti github dll, ini karena Go tidak memiliki repository dependensi publik, sebagian besar proyek open source di-hosting di Gitub, juga ada sebagian yang自行搭建 repository, misalnya google.golang.org/protobuf, golang.org/x/crypto. Biasanya, rangkaian网址 ini juga merupakan nama modul proyek Go, ini akan muncul masalah, URL tidak case-sensitive, tetapi folder penyimpanan dependensi case-sensitive, jadi go get github.com/gin-gonic/gin dan go get github.com/gin-gonic/Gin mereferensikan dependensi yang sama tetapi path penyimpanan lokal berbeda. Saat terjadi situasi ini, Go tidak langsung menggunakan huruf besar sebagai path penyimpanan, tetapi akan meng-escapenya menjadi !huruf kecil, misalnya github.com\BurntSushi akhirnya akan di-escape menjadi github.com\!burnt!sushi.
module
Keyword module mendeklarasikan nama modul proyek saat ini, satu file go.mod hanya boleh muncul satu keyword module. Contoh中的
module golearnMewakili nama modul saat ini adalah golearn, misalnya membuka file go.mod dependensi Gin dapat发现 nama modulenya
module github.com/gin-gonic/ginNama modul Gin adalah alamat yang digunakan saat mendownload dependensi, ini juga format nama modul yang direkomendasikan, domain/user/nama repository.
TIP
Ada satu hal yang perlu diperhatikan, saat major version lebih besar dari 1, nomor major version harus tercermin di nama modul, misalnya
github.com/my/exampleJika versi upgrade ke v2.0.0, maka nama modul perlu dimodifikasi menjadi berikut
github.com/my/example/v2Jika proyek原有 mereferensikan versi lama, dan versi baru tidak membedakan, saat mereferensikan dependensi karena path sama, sehingga user tidak dapat membedakan perubahan major version yang带来的 perubahan tidak kompatibel, ini mungkin menyebabkan error program.
Deprecation
Komentar Deprecated di baris pertama atas module untuk表示 modul ini sudah di-deprecate, misalnya
// Deprecated: use example.com/mod/v2 instead.
module example.com/modgo
Keyword go表示 versi Go yang digunakan untuk menulis proyek saat ini, nomor versi harus mengikuti aturan semantic versioning, sesuai versi go yang berbeda, Go Mod akan menunjukkan perilaku yang berbeda, berikut adalah contoh sederhana, tentang versi Go yang tersedia自行前往官方查阅.
go 1.20require
Keyword require表示 mengimport dependensi eksternal, misalnya
require github.com/gin-gonic/gin v1.9.0Formatnya adalah require nama_modul nomor_versi, saat ada banyak require dapat menggunakan kurung
require (
github.com/bytedance/sonic v1.8.0 // indirect
)Dengan komentar // indirect表示 dependensi ini tidak langsung direferensikan oleh proyek saat ini, mungkin dependensi yang direferensikan langsung proyek mereferensikan dependensi tersebut, jadi bagi proyek saat ini adalah indirect reference. Sebelumnya disebutkan saat major version berubah harus tercermin di nama modul, jika tidak mengikuti aturan ini modul disebut modul tidak standar, saat require, akan ditambahkan komentar incompatible.
require example.com/m v4.1.2+incompatiblePseudo Version
Di file go.mod di atas, dapat发现 ada beberapa versi dependensi package bukan nomor versi semantic, tetapi string yang tidak jelas, ini sebenarnya adalah CommitID versi yang sesuai, versi semantic biasanya mengacu pada某一 Release. Nomor versi pseudo dapat diperkecil ke某一 Commit tertentu, format biasanya adalah vx.y.z-yyyyMMddHHmmss-CommitId, karena vx.y.znya tidak一定 benar ada, oleh karena itu disebut versi pseudo, misalnya v0.0.0 di contoh berikut tidak ada, yang benar-benar efektif adalah 12位 CommitID setelahnya.
// CommitID umumnya ambil 12位 pertama
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirectDemikian juga, saat mendownload dependensi juga dapat menentukan CommitID menggantikan nomor versi semantic
go get github.com/chenzhuoyu/base64x@fe3a3abad311exclude
Keyword exclude表示 tidak memuat dependensi versi yang ditentukan, jika sekaligus ada require yang mereferensikan versi yang sama, juga akan diabaikan. Keyword ini hanya efektif di modul utama. Misalnya
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 akan menggantikan dependensi versi yang ditentukan, dapat menggunakan path modul dan versi untuk menggantikan atau path file yang ditentukan platform lain, contoh
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
)Hanya versi di sebelah kiri => yang digantikan, versi lain dari dependensi yang sama tetap dapat diakses normal, baik menggunakan path lokal atau path modul untuk menentukan penggantian, jika modul penggantian memiliki file go.mod, maka module directive-nya harus cocok dengan path modul yang digantikan.
retract
Directive retract表示, tidak boleh bergantung pada versi atau rentang versi dependensi yang ditentukan retract. Misalnya setelah merilis versi baru发现 ada masalah serius, saat ini dapat menggunakan directive retract.
Menarik kembali beberapa versi
retract (
v1.0.0 // Published accidentally.
v1.0.1 // Contains retractions only.
)Menarik kembali rentang versi
retract v1.0.0
retract [v1.0.0, v1.9.9]
retract (
v1.0.0
[v1.0.0, v1.9.9]
)go.sum
File go.sum saat awal membuat proyek tidak akan ada, hanya setelah benar-benar mengimport dependensi eksternal, baru akan menghasilkan file ini, file go.sum tidak cocok untuk dibaca manusia, juga tidak disarankan memodifikasi file ini secara manual. Fungsinya terutama untuk menyelesaikan masalah build yang konsisten, yaitu orang yang berbeda di lingkungan yang berbeda menggunakan proyek yang sama saat build dependensi package yang direferensikan harus sama persis, ini hanya mengandalkan satu file go.mod tidak dapat dijamin.
Selanjutnya lihat apa yang dilakukan Go dari awal sampai akhir saat mendownload dependensi, pertama gunakan command berikut untuk mendownload dependensi
go get github.com/bytedance/sonic v1.8.0Command go get pertama akan mendownload dependensi package ke direktori cache lokal, biasanya direktori ini adalah $GOMODCACHE/cache/download/, direktori ini dibagi sesuai nama domain untuk dependensi website yang berbeda, jadi Anda mungkin melihat struktur direktori seperti berikut
$ 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/Maka path penyimpanan dependensi yang didownload pada contoh di atas terletak di
$GOMODCACHE/cache/download/github.com/bytedance/sonic/@v/Struktur direktori yang mungkin sebagai berikut, akan ada beberapa file yang dinamai versi
$ 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.ziphashBiasanya, di direktori ini pasti ada file list, digunakan untuk merekam nomor versi yang diketahui dari dependensi tersebut, dan untuk setiap versi, akan ada file seperti berikut:
zip: compressed package source code dependensiziphash: nilai hash yang dihitung berdasarkan compressed package dependensiinfo: metadata versi format jsonmod: filego.modversi inilock: file temporary,官方 juga tidak mengatakan untuk apa
Umumnya, Go akan menghitung nilai hash dari dua file compressed package dan go.mod, lalu query nilai hash dependensi tersebut sesuai server yang ditentukan GOSUMDB (default adalah sum.golang.org), jika nilai hash yang dihitung lokal tidak konsisten dengan hasil query, maka tidak akan melanjutkan. Jika konsisten, akan update file go.mod, dan menyisipkan dua catatan ke file go.sum, kira-kira sebagai berikut:
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=TIP
Jika GOSUMDB dinonaktifkan, Go akan langsung menulis nilai hash yang dihitung lokal ke file go.sum, umumnya tidak disarankan melakukan ini.
Normalnya setiap dependensi akan memiliki dua catatan, yang pertama adalah nilai hash compressed package, yang kedua adalah nilai hash file go.mod dependensi package, format catatan adalah nama_modul nomor_versi nama_algoritma:nilai_hash, beberapa dependensi package yang lebih tua mungkin tidak memiliki file go.mod, jadi tidak akan ada catatan hash kedua. Saat proyek ini di-build di lingkungan orang lain, Go akan menghitung nilai hash dependensi lokal yang ditentukan di go.mod, lalu bandingkan dengan nilai hash yang dicatat di go.sum, jika nilai hash tidak konsisten,说明 versi dependensi berbeda, akan menolak build. Saat terjadi situasi ini, dependensi lokal dan file go.sum keduanya mungkin telah dimodifikasi, tetapi karena file go.sum adalah catatan query GOSUMDB, jadi akan cenderung lebih percaya file go.sum.
Modul Privat
Sebagian besar tool Go Mod ditujukan untuk proyek open source, namun Go juga mendukung modul privat. Untuk proyek privat, biasanya perlu mengkonfigurasi beberapa environment configuration berikut untuk menangani modul privat
GOPROXY: kumpulan proxy server dependensiGOPRIVATE: daftar pola umum prefix path modul privat, jika nama modul sesuai aturan表示 modul ini adalah modul privat, perilaku spesifik sama dengan GONOPROXY dan GONOSUMDB.GONOPROXY: daftar pola umum prefix path modul yang tidak didownload dari proxy, jika sesuai aturan saat mendownload modul tidak akan lewat GOPROXY, coba langsung download dari version control system.GONOSUMDB: daftar pola umum prefix path modul yang tidak melakukan validasi publik GOSUMDB, jika sesuai saat mendownload modul validasi tidak akan lewat database publik checksum.GOINSECURE: daftar pola umum prefix path modul yang dapat diambil melalui HTTP dan protokol tidak aman lainnya.
Workspace
Sebelumnya disebutkan file go.mod mendukung directive replace, ini memungkinkan kita暂时 menggunakan modifikasi lokal yang belum sempat dirilis, sebagai berikut
replace (
github.com/246859/hello v1.0.1 => ./hello
)Saat kompilasi, go akan menggunakan modul hello lokal, setelah merilis versi baru di masa depan lalu hapus.
Tetapi jika menggunakan directive replace akan memodifikasi konten file go.mod, dan modifikasi ini mungkin salah submit ke repository remote, ini adalah hal yang tidak kita harapkan, karena target yang ditentukan directive replace adalah path file bukan URL network, path yang dapat digunakan di mesin ini mungkin tidak dapat digunakan di mesin lain, path file juga akan menjadi masalah besar dalam hal cross-platform. Untuk menyelesaikan masalah seperti ini, workspace pun muncul.
Workspace, adalah solusi baru tentang manajemen multi-modul yang diperkenalkan Go di 1.18, bertujuan untuk lebih baik melakukan pekerjaan pengembangan multi-modul lokal, berikut akan menjelaskan melalui contoh.
Repository contoh: 246859/work: go work example (github.com)
Contoh
Pertama di bawah proyek ada dua modul go independen, masing-masing adalah auth, user
$ ls -1
LICENSE
README.md
auth
go.work
userModul auth bergantung pada struct User dari modul user, konten sebagai berikut
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")
}Konten modul user sebagai berikut
package user
type User struct {
Name string
Password string
Age int
}Di proyek ini, kita dapat menulis file go.work seperti ini
go 1.22
use (
./auth
./user
)Kontennya sangat mudah dipahami, menggunakan directive use, menentukan modul mana yang berpartisipasi dalam kompilasi, selanjutnya jalankan kode di modul auth
// 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)
}Jalankan command berikut, dari hasil得知 berhasil mengimport modul.
$ go run ./auth/example
trueDi versi sebelumnya, untuk dua modul independen ini, jika modul auth ingin menggunakan kode dari modul user hanya ada dua cara
- Submit modifikasi modul user dan push ke repository remote, rilis versi baru, lalu modifikasi file
go.modmenjadi versi yang ditentukan - Modifikasi file
go.modredirect dependensi ke file lokal
Kedua cara perlu memodifikasi file go.mod, dan keberadaan workspace adalah untuk dapat mengimport modul lain tanpa memodifikasi file go.mod. Namun perlu dipahami satu hal, file go.work hanya digunakan selama pengembangan, keberadaannya hanya untuk lebih nyaman melakukan pengembangan lokal, bukan untuk manajemen dependensi, ia hanya暂时 membuat Anda melewatkan proses submit ke rilis, memungkinkan Anda segera menggunakan modifikasi baru modul user tanpa harus menunggu, saat modul user test selesai, terakhir tetap perlu merilis versi baru, dan modul auth terakhir tetap harus memodifikasi file go.mod untuk mengimport versi terbaru (proses ini dapat diselesaikan dengan command go work sync), oleh karena itu selama proses pengembangan go normal, go.work juga tidak boleh submit ke VCS (file go.work di repository contoh hanya untuk demonstrasi), karena kontennya bergantung pada file lokal, dan fungsinya juga terbatas pada pengembangan lokal.
Command
Berikut adalah beberapa command workspace
| Command | Penjelasan |
|---|---|
| edit | Mengedit go.work |
| init | Menginisialisasi workspace baru |
| sync | Mensinkronkan dependensi modul workspace |
| use | Menambahkan modul baru ke go.work |
| vendor | Menyalin dependensi sesuai format vendor |
前往 go work cmd了解更多 informasi terkait command
Directive
Konten file go.work sangat sederhana, hanya tiga directive
go, menentukan versi gouse, menentukan modul yang digunakanreplace, menentukan modul yang digantikan
Selain directive use, dua lainnya pada dasarnya setara dengan directive di go.mod, hanya saja directive replace di go.work akan berlaku untuk semua modul, satu go.work lengkap sebagai berikut.
go 1.22
use(
./auth
./user
)
repalce github.com/246859/hello v1.0.0 => /home/jack/code/hello