Benarkah GOPATH dan GOROOT tidak lagi dibutuhkan?

Kebetulan pengembang yang baru mulai berkenalan dengan Go sering menemui masalah dalam memilih direktori kerja untuk proyek Go. Jadi dalam obrolan konferensi GolangConf pertanyaan ini juga ditanyakan. Para penjual baru sering kali saling menakuti satu sama lain dengan kata-kata GOPATH dan GOROOT . Namun, dalam panduan mulai cepat dengan versi Go saat ini (1.13), kedua kata "menakutkan" ini tidak disebutkan sama sekali.


Mari kita lihat mengapa. Untuk kemurnian percobaan, saya menggunakan Ubuntu baru ke mesin virtual dan menginstal Go sesuai dengan instruksi dari Wiki :


sudo add-apt-repository ppa:longsleep/golang-backports sudo apt-get update sudo apt-get install golang-go 

Go 1.13 diinstal dan siap digunakan:


 $ go version go version go1.13 linux/amd64 $ which go /usr/bin/go $ whereis go go: /usr/bin/go /usr/lib/go /usr/share/go /usr/share/man/man1/go.1.gz 

GOROOT


Tentang GOROOT telah ditulis dengan sempurna dalam artikel tahun 2015 , dan informasi ini masih relevan.


Sangat lucu bahwa di antara daftar direktori yang dikeluarkan oleh perintah terakhir ( whereis go ), GOROOT sebenarnya tidak:


 $ go env GOROOT /usr/lib/go-1.13 

Jadi, misalnya, jika untuk IDE saya perlu menentukan path ke file dari Go library standar, saya akan menentukan /usr/lib/go-1.13 . Mungkin, dalam skenario ini, penggunaan GOROOT dalam kehidupan sehari-hari berakhir.


GOPATH dan modul


Tampaknya di tempat ini perlu terburu-buru untuk menginstal GOPATH , tetapi saya tidak akan melakukan ini. Sebenarnya GOPATH sudah disetel:


 $ go env GOPATH /home/elena/go 

Saya nyaman dengan GOPATH di ~/go , yang berarti saya tidak akan mengubahnya.


Saya akan segera membuat direktori untuk proyek pertama saya di Go. Ini dapat dilakukan di mana saja, misalnya, tepat di direktori home Anda. Selain itu, saya akan segera mulai bekerja dengan alat Modul Go :


 $ mkdir ~/hello $ go mod init github.com/rumyantseva/hello go: creating new go.mod: module github.com/rumyantseva/hello 

Untuk perintah go mod init , saya menentukan jalur modul modul unik untuk proyek saya. Dengan cara ini, proksi atau alat lain, jika perlu, dapat menemukan file proyek saya.


Setelah memanggil perintah go mod init , direktori go mod init muncul di direktori home saya:


 $ tree ~/go /home/elena/go └── pkg └── mod └── cache └── lock 3 directories, 1 file 

Dalam hal ini, file kunci (di bagian paling bawah pohon) masih kosong.


File go.mod muncul di go.mod ~/hello dengan konten berikut:


 module github.com/rumyantseva/hello go 1.13 

Di go.mod semua informasi tentang dependensi modul saya selanjutnya akan disimpan.


Sekarang mari kita menulis aplikasi menggunakan dependensi eksternal. Di direktori ~/hello , saya membuat file main.go dan menulis kode berikut ke dalamnya:


 package main import ( "github.com/sirupsen/logrus" ) func main() { logrus.Info("Hello, world!") } 

Tentu saja dalam kehidupan nyata untuk menulis "Halo, dunia!" Anda dapat melakukannya tanpa logrus , tetapi dalam contoh ini, perpustakaan ini akan membantu kami mencari tahu di mana file-file dependensi eksternal disimpan.


Saya meluncurkan aplikasi dengan cara paling sederhana:


 $ go run main.go go: finding github.com/sirupsen/logrus v1.4.2 go: downloading github.com/sirupsen/logrus v1.4.2 go: extracting github.com/sirupsen/logrus v1.4.2 go: downloading golang.org/x/sys v0.0.0-20190422165155-953cdadca894 go: extracting golang.org/x/sys v0.0.0-20190422165155-953cdadca894 go: finding golang.org/x/sys v0.0.0-20190422165155-953cdadca894 INFO[0000] Hello, world! 

Sebelum aplikasi dibangun dan diluncurkan, alat go mod berfungsi. Dia mendefinisikan dependensi eksternal saya github.com/sirupsen/logrus , mengambil versi terbarunya v1.4.2 dan menggunakan dependensi transitif.


Baris ditambahkan ke file go.mod dengan deskripsi ketergantungan pada logrus :


 module github.com/rumyantseva/hello go 1.13 require github.com/sirupsen/logrus v1.4.2 // indirect 

File go.sum juga muncul, di mana, di samping hash dari dependensi logrus , informasi tentang hash dependensi transitif disimpan:


 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 

Di mana kode ketergantungan itu sendiri? Itu dapat ditemukan di ~/go/pkg/mod . Juga, checksum dan informasi overhead lainnya untuk bekerja dengan dependensi akan disimpan di ~/go/pkg .


Jika Anda sudah menemukan alat go get , Anda tahu bahwa ketika menarik dependensi, sebenarnya klon repositori (misalnya, dalam kasus git dengan git clone ). Tapi go mod tidak bekerja seperti itu. Untuk go mod unit utama kode adalah modul. Modul adalah arsip. Ketika bekerja dengan dependensi go mod , ia secara eksplisit (jika Anda go mod download perintah go mod download ) atau secara implisit (jika Anda mulai mengompilasi aplikasi) mengunduh dan membongkar arsip melalui GOPROXY . Mari kita lihat bagaimana proxy diset pada Go 1.13 secara default:


 $ go env GOPROXY https://proxy.golang.org,direct 

Jadi, sebagai proxy saat membangun "Halo, Dunia!" digunakan oleh proxy.golang.org . Tentu saja, variabel ini dapat diubah dengan memilih repositori modul yang berbeda. Misalnya, Anda dapat menggunakan perusahaan proxy internal Anda sendiri, yang akan disimpan, termasuk perpustakaan internal, yang kodenya tidak dipublikasikan dalam sumber terbuka.


Secara umum, jika saya memulai proyek baru dan tidak keberatan menggunakan Modul Go, saya mungkin tidak tahu apa-apa tentang GOPATH . Go akan membuat direktori ~/go dengan sendirinya saat dibutuhkan.


Kapan GOPATH dibutuhkan?


Jika pada dasarnya Anda tidak menggunakan Modul Go (misalnya, dalam proyek lawas), menjauh dari pekerjaan yang lebih eksplisit dengan GOPATH mungkin tidak sesederhana itu.


Untuk melihat apa yang akan terjadi pada proyek saya, jika saya memutuskan untuk tidak menggunakan go mod , hapus file ~/hello/go.mod dan ~/hello/go.sum . Saya juga akan menghapus ~/go untuk kembali ke keadaan sistem yang saya miliki di awal:


 rm -rf ~/go ~/hello/go.mod ~/hello/go.sum 

Hanya file main.go tersisa di main.go ~/hello . Apa yang terjadi sekarang jika saya mencoba menjalankannya dengan go run ?


 $ go run main.go main.go:4:2: cannot find package "github.com/sirupsen/logrus" in any of: /usr/lib/go-1.13/src/github.com/sirupsen/logrus (from $GOROOT) /home/elena/go/src/github.com/sirupsen/logrus (from $GOPATH) 

Inilah mereka, GOROOT dan GOROOT menakutkan ini :)


Untuk mengkompilasi aplikasi, saya perlu menarik ketergantungan pada GOPATH . Saya melakukan ini dengan go get old go get :


 $ go get -v github.com/sirupsen/logrus github.com/sirupsen/logrus (download) created GOPATH=/home/elena/go; see 'go help gopath' get "golang.org/x/sys/unix": found meta tag get.metaImport{Prefix:"golang.org/x/sys", VCS:"git", RepoRoot:"https://go.googlesource.com/sys"} at //golang.org/x/sys/unix?go-get=1 get "golang.org/x/sys/unix": verifying non-authoritative meta tag golang.org/x/sys (download) golang.org/x/sys/unix github.com/sirupsen/logrus 

Apa yang terjadi Pertama-tama, GOPATH direktori ~/go (yang ditentukan sebagai GOPATH ). Kemudian proses kloning repositori dengan dependensi dimulai. Sangat lucu bahwa repositori kloning terlihat jauh lebih lambat daripada opsi ketika kita menggunakan go mod untuk mengunduh dan membongkar modul. Namun, kode dependensi sekarang dapat ditemukan di dalam ~/go/src/ .


Ngomong-ngomong, masih belum ada git client pada instalasi Ubuntu saya yang bersih, dan agar go get bekerja, saya harus menginstalnya.


Saya meluncurkan aplikasi:


 $ go run main.go INFO[0000] Hello, world! 

Itu berhasil!


Itu hanya di tingkat aplikasi, saya sekarang tidak melacak versi dependensi eksternal. Bagaimana jika, karena kerentanan, pada suatu titik di repositori github.com/sirupsen/logrus bukan logger yang saya harapkan, tetapi beberapa kode berbahaya? Cepat atau lambat, saya masih memerlukan alat untuk bekerja dengan dependensi, dan jika Go Modul untuk beberapa alasan tidak cocok, Anda harus mencari sesuatu yang lain ...


Kesimpulan


Artikel ini tidak membahas beberapa poin tertentu, dan bekerja dengan dependensi eksternal di Go masih dapat menimbulkan banyak pertanyaan. Namun, versi baru Go setidaknya tidak memberlakukan batasan di mana direktori kerja proyek Anda dapat dibuat.


Jika Anda memulai proyek baru, coba Go Modul! Kembali ke pendekatan lama untuk bekerja dengan dependensi masuk akal hanya jika terjadi kesalahan. Omong-omong, jika Anda lebih suka menyimpan semua dependensi di dalam proyek, Go Modul mendukung mode vendor.


Jika Anda perlu bekerja dengan proyek yang sudah ada, dan untuk beberapa alasan Anda tidak ingin menerjemahkannya ke dalam Modul Go, penting untuk menunjukkan dalam dokumentasi untuk proyek fitur-fitur dari penerapan dan manajemen ketergantungannya. Jika pendatang baru yang tidak terbiasa dengan pendekatan lama untuk bekerja dengan dependensi datang ke proyek, akan lebih mudah bagi mereka untuk berurusan dengan proyek jika semua dokumentasi sudah ada.


Ngomong-ngomong, pada tanggal 7 Oktober di konferensi GolangConf , sebagai salah satu kegiatan khusus, kami sedang merencanakan zona ahli di mana siapa pun dapat mengajukan pertanyaan tentang Pergi ke anggota komite program konferensi dan penggemar komunitas Go Rusia. Pasang Go? Menangani kecanduan? Menulis layanan mikro? Ini untuk kita!

Source: https://habr.com/ru/post/id467697/


All Articles