Halo semuanya. Untuk mengantisipasi dimulainya kursus Pengembang Golang, kami telah menyiapkan terjemahan lain yang menarik untuk Anda.
Modul adalah cara untuk menangani dependensi di Go. Awalnya disajikan sebagai percobaan, modul seharusnya diperkenalkan ke lapangan sebagai standar baru untuk mengelola paket dari versi 1.13.Saya menemukan topik ini cukup tidak biasa bagi pemula yang berasal dari bahasa lain, jadi saya memutuskan untuk mengumpulkan beberapa pemikiran dan tips di sini untuk membantu orang lain seperti saya mendapatkan ide manajemen paket di Go. Kami akan mulai dengan pengenalan umum, dan kemudian beralih ke aspek yang kurang jelas, termasuk menggunakan folder vendor, menggunakan modul dengan Docker dalam pengembangan, dependensi alat, dll.Jika Anda sudah terbiasa dengan modul Go dan mengetahui Wiki, seperti punggung tangan Anda, artikel ini mungkin tidak akan sangat membantu Anda. Tetapi untuk sisanya, bagaimanapun, ini dapat menghemat beberapa jam coba-coba.Jadi, jika Anda sedang dalam perjalanan, melompatlah dan nikmati perjalanannya.
Mulai cepat
Jika kontrol versi sudah terintegrasi dalam proyek Anda, Anda bisa menjalankannyago mod init
Atau tentukan jalur ke modul secara manual. Ini adalah sesuatu seperti nama, URL, dan jalur impor untuk paket Anda:go mod init github.com/you/hello
Ini akan membuat file go.mod
, yang juga mendefinisikan persyaratan dan lochit proyek tergantung pada versi yang benar (sebagai analogi untuk Anda, seperti package.json
, dan package-lock.json
digabungkan menjadi satu file):module github.com/you/hello
go 1.12
Jalankan go get
untuk menambahkan dependensi baru ke proyek Anda:Perhatikan bahwa meskipun Anda tidak dapat menentukan rentang versi dengan get get, apa yang Anda tetapkan di sini bukanlah versi spesifik, tetapi versi minimum. Seperti yang akan kita lihat nanti, ada cara untuk memperbarui dependensi dengan anggun menurut semver.# use Git tags
go get github.com/go-chi/chi@v4.0.1
# or Git branch name
go get github.com/go-chi/chi@master
# or Git commit hash
go get github.com/go-chi/chi@08c92af
Sekarang file kami adalah go.mod
sebagai berikut:module github.com/you/hello
go 1.12
require github.com/go-chi/chi v4.0.2+incompatible
Sufiks +incompatible
ditambahkan ke semua paket yang belum dikonfigurasi untuk modul Go atau melanggar aturan kontrol versinya.Karena kami belum mengimpor paket ini di mana pun di proyek kami, itu ditandai sebagai // indirect
. Kita dapat merapikan ini dengan perintah berikut:go mod tidy
Bergantung pada kondisi repositori Anda saat ini, ia akan menghapus modul yang tidak digunakan atau menghapus komentar // indirect
.Jika ada dependensi dengan sendirinya tidak memiliki go.mod
(misalnya, itu belum dikonfigurasi untuk modul), maka semua dependensinya akan ditulis ke file induk go.mod
(sebagai opsi, file Anda go.mod)
bersama dengan komentar // indirect
untuk menunjukkan bahwa mereka bukan dari impor langsung Dalamrencana global Anda , tujuannya go mod tidy
adalah untuk menambahkan dependensi yang diperlukan untuk kombinasi OS, arsitektur, dan tag build lainnya. Pastikan untuk menjalankannya sebelum setiap rilis.Pastikan juga file dibuat setelah menambahkan dependensigo.sum
. Anda mungkin berpikir bahwa ini adalah file kunci. Tetapi sebenarnya itu go.mod
sudah memberikan informasi yang cukup untuk membangun 100% direproduksi. File go.sum
ini dibuat untuk keperluan verifikasi: itu berisi checksum kriptografi yang diharapkan dari isi masing-masing versi modul.Sebagian karena ini go.sum
bukan file kunci, ini menyimpan checksum tertulis untuk versi modul bahkan setelah Anda berhenti menggunakan modul ini. Ini memungkinkan Anda untuk memeriksa checksum jika Anda melanjutkan menggunakannya nanti, yang menyediakan keamanan tambahan.
Mkcert baru saja bermigrasi ke modul (dengan vendor / untuk kompatibilitas mundur) dan semuanya berjalan lancar
https://github.com/FiloSottile/mkcert/commit/26ac5f35395fb9cba3805faf1a5a04d260271291
$ GO111MODULE=on go1.11rc1 mod init
$ GO111MODULE=on go1.11rc1 mod vendor
$ git add go.mod go.sum vendor
$ git rm Gopkg.lock Gopkg.toml Makefile

FAQ: Haruskah saya komit go.sum
di git?
A: Jelas ya. Dengan itu, pemilik sumber Anda tidak perlu mempercayai repositori GitHub lain dan pemilik jalur impor khusus. Sudah dalam perjalanan ke kami, sesuatu yang lebih baik, tetapi untuk sekarang ini adalah model yang sama dengan hash dalam file kunci.
Perintah go build
dan go test
akan secara otomatis memuat semua dependensi yang hilang, meskipun Anda dapat melakukan ini secara eksplisit dengan bantuan go mod download
cache lokal pra-populasi yang mungkin berguna untuk CI.Secara default, semua paket kami dari semua proyek dimuat ke direktori $GOPATH/pkg/mod
. Kami akan membahas ini secara lebih rinci nanti.Memutakhirkan Versi Paket
Anda dapat menggunakan go get -u
masing go get -u=patch
- masing untuk memperbarui dependensi ke versi minor terbaru atau tambalan.Tetapi Anda tidak dapat memutakhirkan ke versi utama seperti itu. Kode yang termasuk dalam modul Go harus secara teknis mematuhi aturan berikut:- Cocokkan semver (contoh tag VCS v1.2.3).
- Jika modul adalah versi v2 atau lebih tinggi, versi utama modul harus dimasukkan
/vN
di akhir lintasan modul yang digunakan dalam file go.mod
dan di lintasan impor paket:
import "github.com/you/hello/v2"
Rupanya, ini dilakukan agar berbagai versi paket dapat diimpor dalam satu rakitan (lihat masalah ketergantungan berlian ).Singkatnya, Go mengharapkan Anda untuk sangat berhati-hati saat memperkenalkan versi utama.Mengganti modul yang diimpor
Anda dapat menentukan modul yang diperlukan untuk garpu Anda sendiri atau bahkan jalur lokal ke file menggunakan arahan replace
:go mod edit -replace github.com/go-chi/chi=./packages/chi
Hasil:module github.com/you/hello
go 1.12
require github.com/go-chi/chi v4.0.2+incompatible
replace github.com/go-chi/chi => ./packages/chi
Anda dapat menghapus garis secara manual atau menjalankan:go mod edit -dropreplace github.com/go-chi/chi
Manajemen Ketergantungan Proyek
Secara historis, semua kode Go disimpan dalam satu mono-repositori raksasa, karena itulah cara Google mengatur basis kodenya, dan ini memengaruhi desain bahasa.Modul Go adalah titik berangkat dari pendekatan ini. Anda tidak perlu lagi menyimpan semua proyek Anda $GOPATH
.Namun, secara teknis semua dependensi yang Anda unduh masih ditempatkan $GOPATH/pkg/mod
. Jika Anda menggunakan wadah Docker untuk pengembangan lokal, ini bisa menjadi masalah, karena dependensi disimpan di luar proyek. Secara default, mereka tidak terlihat di IDE Anda.
Ini biasanya bukan masalah untuk bahasa lain, tapi inilah yang pertama kali saya temui ketika bekerja dengan basis kode Go.Untungnya, ada beberapa cara (tidak berdokumen) untuk menyelesaikan masalah ini.Opsi 1. Instal GOPATH di dalam direktori proyek Anda.
Pada pandangan pertama, ini mungkin tampak berlawanan dengan intuisi, tetapi jika Anda menjalankan Go from a container , Anda dapat mengesampingkan GOPATH sehingga menunjuk ke direktori proyek sehingga paket-paket dapat diakses dari host:version: '3.7'
services:
app:
command: tail -f /dev/null
image: golang:1.12.6-stretch
environment:
# - /code/.go/pkg/mod
- GOPATH=/code/.go
ports:
- 8000:8000
volumes:
- ./:/code:cached
working_dir: /code
IDE populer harus dapat menginstal GOPATH di tingkat proyek (ruang kerja):
Satu-satunya kelemahan dari pendekatan ini adalah kurangnya interaksi dengan runtime Go pada komputer host. Anda harus menjalankan semua perintah Go di dalam wadah.Opsi 2: Penjual Otomatis Ketergantungan Anda
Cara lain adalah dengan menyalin dependensi proyek Anda ke folder vendor
:go mod vendor
Ini harus segera dicatat: kami TIDAK mengizinkan Pergi untuk langsung mengunggah materi ke folder vendor: ini tidak mungkin dengan modul. Kami cukup menyalin paket yang sudah diunduh.Selain itu, jika Anda melepaskan dependensi Anda, seperti dalam contoh di atas, lalu hapus $GOPATH/pkg/mod
lalu coba tambahkan beberapa dependensi baru ke proyek Anda, Anda akan melihat yang berikut:- Go akan membangun kembali cache unduhan untuk semua paket perangkat lunak
$GOPATH/pkg/mod/cache
. - Semua modul yang dimuat akan disalin ke
$GOPATH/pkg/mod
. - Dan akhirnya, Go akan menyalin modul-modul ini ke
vendor
folder, menghapus contoh, tes, dan beberapa file lain yang tidak Anda andalkan secara langsung.
Selain itu, ada banyak hal yang hilang di folder vendor yang baru dibuat ini:
File penulisan Docker khas terlihat seperti ini (perhatikan binding volume):version: '3.7'
services:
app:
command: tail -f /dev/null
image: golang:1.12.6-stretch
ports:
- 8000:8000
volumes:
# go,
- modules:/go/pkg/mod/cache
- ./:/code:cached
working_dir: /code
volumes:
modules:
driver: local
Harap dicatat bahwa saya TIDAK komik folder vendor ini dalam sistem kontrol versi atau saya tidak akan menggunakannya dalam produksi. Ini adalah skrip pengembangan yang sepenuhnya lokal, yang biasanya dapat ditemukan dalam beberapa bahasa lain.Namun, ketika saya membaca komentar dari beberapa pengelola Go dan beberapa penawaran terkait dengan vending parsial (?), Saya mendapat kesan bahwa fitur ini pada awalnya dimaksudkan bukan untuk kasus pengguna ini.Salah satu komentator di reddit membantu saya menjelaskan hal ini:Biasanya orang-orang menjual dependensi mereka untuk alasan-alasan seperti keinginan untuk memiliki perangkat ketat tanpa akses ke jaringan, serta salinan dependensi siap pakai jika terjadi kegagalan github atau menghilangnya repositori, dan kemungkinan audit yang lebih mudah terhadap perubahan dependensi menggunakan alat VCS standar, dll. .Ya, itu tidak terlihat seperti sesuatu dari kenyataan bahwa aku mungkin akan tertarik.Menurut perintah Go, Anda dapat dengan mudah mengaktifkan vending dengan mengatur variabel lingkungan GOFLAGS=-mod=vendor
. Saya tidak merekomendasikan melakukan ini. Menggunakan flag hanya akan pecah go get
tanpa memberikan manfaat lain untuk alur kerja harian Anda:
Faktanya, satu-satunya tempat yang Anda butuhkan untuk mengaktifkan vending adalah IDE Anda:
Setelah beberapa percobaan dan kesalahan, saya datang dengan prosedur berikut untuk menambahkan dependensi vendor dalam pendekatan ini.Langkah 1. Persyaratan
Anda dapat memerlukan ketergantungan dengan go get
:go get github.com/rs/zerolog@v1.14.3
Langkah 2. Impor
Kemudian impor di suatu tempat di kode Anda:import (
_ "github.com/rs/zerolog"
)
Langkah 3. Penjual
Terakhir, buka kembali dependensi Anda:go mod vendor
Ada proposal yang tertunda untuk memungkinkan vendor mod untuk menerima templat modul tertentu yang mungkin (atau mungkin tidak) menyelesaikan beberapa masalah yang terkait dengan alur kerja ini.go mod vendor
sudah secara otomatis membutuhkan impor yang terlewat, jadi langkah 1 adalah opsional dalam alur kerja ini (jika Anda tidak ingin menentukan batasan versi). Namun, tanpa langkah 2, itu tidak akan mengambil paket yang diunduh.Pendekatan ini berfungsi lebih baik dengan sistem host, tetapi agak membingungkan ketika harus mengedit dependensi Anda.
Secara pribadi, saya pikir mendefinisikan ulang GOPATH adalah pendekatan yang lebih bersih karena tidak mengorbankan fungsionalitas go get
. Namun demikian, saya ingin menunjukkan kedua strategi tersebut, karena folder vendor mungkin lebih akrab bagi orang-orang yang berasal dari bahasa lain, seperti PHP, Ruby, Javascript, dll. Seperti yang dapat Anda lihat dari penipuan yang dijelaskan dalam artikel ini, ini bukan pilihan yang sangat baik untuk Go.Ketergantungan alat
Kita mungkin perlu menginstal beberapa alat berbasis-Go yang tidak diimpor, tetapi digunakan sebagai bagian dari lingkungan pengembangan proyek. Contoh sederhana dari alat tersebut adalah CompileDaemon , yang dapat memonitor kode Anda untuk perubahan dan memulai kembali aplikasi Anda. Pendekatan yangdirekomendasikan secara resmi adalah menambahkan tools.go
file (nama tidak masalah) dengan konten berikut:
package tools
import (
_ "github.com/githubnemo/CompileDaemon"
)
- Batasan
// +build tools
mencegah majelis reguler Anda dari benar-benar mengimpor alat Anda. - Ekspresi impor memungkinkan perintah go untuk secara akurat menulis informasi versi alat
go.mod
Anda ke file modul Anda.
Jadi itu saja. Saya harap Anda tidak akan bingung seperti ketika saya mulai menggunakan modul Go. Anda dapat mengunjungi wiki Go Modul untuk lebih jelasnya.
Ikuti saja.