Apa yang dimaksud dengan go build? (mulai membangun vs. mulai menginstal)

106

Pemrogram Go baru sering kali tidak tahu atau bingung apa fungsi perintah dasar go build.

Apa tepatnya yang dibuat go builddan go installperintah dan di mana mereka meletakkan hasil / keluaran?

icza
sumber

Jawaban:

125

Apa yang dilakukan goperintah itu tergantung pada apakah kita menjalankannya untuk paket "normal" atau untuk "main"paket khusus .

Untuk paket

  • go build  membangun paket Anda lalu membuang hasilnya .
  • go installbuild kemudian menginstal paket tersebut di $GOPATH/pkgdirektori Anda .

Untuk perintah (paket main)

  • go build  membangun perintah dan meninggalkan hasilnya di direktori kerja saat ini .
  • go installmembangun perintah di direktori sementara lalu memindahkannya ke $GOPATH/bin.

Untuk apa lulus go build?

Anda dapat mengirimkan paket ke go build, paket yang ingin Anda buat. Anda juga dapat memberikan daftar .gofile dari satu direktori, yang kemudian diperlakukan sebagai daftar file sumber yang menetapkan satu paket.

Jika tidak ada paket (jalur impor) yang disediakan, build akan diterapkan pada direktori saat ini.

Jalur impor mungkin berisi satu atau beberapa karakter "..."pengganti (dalam hal ini adalah pola ). ...bisa cocok dengan sembarang string, misalnya net/...cocok dengan netpaket dan paket yang ada di subfoldernya. Perintah

go build ./...

sering digunakan untuk membangun paket di folder saat ini dan semua paket berulang. Perintah ini dikeluarkan di root proyek membangun proyek lengkap.

Untuk lebih lanjut tentang menentukan paket, jalankan go help packages.

Tentang modul

Dukungan awal untuk modul Go diperkenalkan di Go 1.11, dan modul menjadi default yang dimulai dengan Go 1.13. Jika goalat dijalankan dari folder yang berisi go.modfile (atau salah satu orang tua folder saat ini), goalat tersebut berjalan dalam mode sadar modul (mode lama disebut mode GOPATH ).

Dalam mode berbasis modul, GOPATH tidak lagi mendefinisikan arti impor selama build, tetapi masih menyimpan dependensi yang diunduh (dalam GOPATH / pkg / mod) dan perintah yang diinstal (dalam GOPATH / bin, kecuali GOBIN disetel).

Saat membuat modul, apa yang dibangun ditentukan oleh daftar build . Daftar build awalnya hanya berisi modul utama (modul yang berisi direktori tempat goperintah dijalankan), dan dependensi modul utama ditambahkan ke daftar build, secara rekursif (dependensi dependensi juga ditambahkan).

Untuk info lebih lanjut, jalankan go help modules.


Pada dasarnya Anda dapat menggunakan go buildsebagai pemeriksaan bahwa paket dapat dibangun (bersama dengan ketergantungannya) sementara go installjuga (secara permanen) menginstal hasilnya di folder yang tepat dari Anda $GOPATH.

go build akan diam-diam berhenti jika semuanya OK, dan akan memberi Anda pesan kesalahan jika paket tidak dapat dibangun / dikompilasi.

Setiap kali goalat menginstal paket atau biner, ia juga menginstal dependensi apa pun yang dimilikinya, jadi menjalankan go installjuga akan menginstal paket tempat program Anda bergantung (tersedia untuk umum, paket "go gettable"), secara otomatis.

Sebagai permulaan, baca halaman resmi Cara Menulis Kode Go .

Informasi selengkapnya tentang goalat: Perintah pergi

Anda juga bisa mendapatkan bantuan lebih lanjut dengan menjalankan perintah berikut:

go help build

Perlu juga dicatat bahwa memulai Go 1.5 go installjuga menghapus file executable yang dibuat oleh go build( sumber ):

Jika 'go install' (tanpa argumen, artinya direktori saat ini) berhasil, hapus file yang dapat dieksekusi yang ditulis oleh 'go build', jika ada. Ini menghindari meninggalkan biner basi di belakang ...

Untuk melengkapi daftar, go runkompilasi aplikasi Anda ke dalam folder sementara, dan mulai biner yang dapat dieksekusi tersebut. Saat aplikasi keluar, itu membersihkan file sementara dengan benar.

Pertanyaan yang terinspirasi oleh karya Dave Cheney What do build build?

icza
sumber
1
Tampaknya aneh bahwa go install tidak memperbarui executable jika identik dengan yang diinstal sebelumnya ... ada wawasan di sini?
Scott Stensland
14

Untuk paket:

go build: membangun paket Anda lalu membuang hasilnya

Itu tidak benar setelah Go 1.10 (Kuartal 1 2018), terima kasih kepada CL 68116 dan CL 75473 . Lihat utas ini , yang saya rujuk di sini.

Apa tepatnya yang dibuat oleh perintah go buildandgo install

Kapanpun alat go menginstal paket atau biner, ia juga menginstal dependensi apa pun yang dimilikinya, jadi menjalankan go install juga akan menginstal paket tempat program Anda bergantung (tersedia untuk umum, paket "go gettable"), secara otomatis.

Sebenarnya ... go installakan berubah juga dengan Go 1.10, selain cache baru:

Perintah " go install" tidak lagi menginstal dependensi dari paket bernama ( CL 75850 ).

Jika Anda menjalankan " go install foo", satu-satunya yang diinstal adalahfoo .

Sebelumnya, itu bervariasi. Jika dependensi kedaluwarsa, " go install" juga memasang semua dependensi.
Penginstalan implisit dari dependensi selama " go install" menyebabkan banyak kebingungan dan sakit kepala bagi pengguna, tetapi sebelumnya diperlukan untuk mengaktifkan build inkremental.
Tidak lagi.
Menurut kami install what I saidsemantik " " baru akan jauh lebih mudah dipahami, terutama karena jelas dari laporan bug bahwa banyak pengguna sudah mengharapkannya.
Untuk memaksa pemasangan dependensi selama " go install", gunakan " go install -i" baru , dengan analogi dengan " go build -i" dan " go test -i".

Fakta bahwa " go install" digunakan untuk menginstal dependensi yang dibangun kembali menyebabkan kebingungan paling sering dalam hubungannya dengan -a, yang artinya " force rebuild of all dependencies".
Sekarang, " go install -a myprog" akan memaksa pembangunan kembali semua dependensi myprog, serta dependensi myprogitu sendiri, tetapi hanya myprogakan terinstal. (Semua dependensi yang dibangun kembali akan tetap disimpan dalam cache build, tentu saja.)
Membuat kasus ini berfungsi lebih dimengerti sangat penting terutama dalam kaitannya dengan analisis staleness berbasis konten yang baru, karena ini melihat alasan bagus untuk membangun kembali dependensi lebih sering daripada sebelumnya , yang akan meningkatkan jumlah kebingungan "mengapa dependensi saya diinstal".
Misalnya, jika Anda menjalankan " go install -gcflags=-N myprog", yang menginstal filemyprogdibangun tanpa pengoptimalan compiler, tetapi tidak lagi menginstal ulang paket yang myprogdigunakan dari pustaka standar tanpa pengoptimalan compiler.

VonC
sumber
Apakah go build, apakah gets? Saya mengalami kesalahan versi cannot find package "github.com/spf13/cobra" in any of:…. Saya tidak tahu bagaimana cara mengatakannya untuk mendapatkannya. Apakah saya perlu mendapatkan secara eksplisit?
ctrl-alt-delor
@ ctrl-alt-delor Dengan versi Go yang mana? Apakah proyek Anda memiliki go.modfile di dalamnya?
VonC
go version go1.11.4 linux/amd64. Saya tidak tahu tentang go.mod. Saya sedang membangun kembali https://github.com/cbroglie/mustache/blob/master/cmd/mustache/main.go, ini aneh karena saya baru saja membangun seluruh paket, dan saya menggunakan contoh ini sebagai basis, dan saya membuat versi yang lebih mendasar yang berfungsi (tetapi tidak menggunakan pustaka ini). Saya tidak bisa melihat bagaimana itu tidak diinstal dengan paket kumis.
ctrl-alt-delor
@ ctrl-alt-delor jadi cobr adalah vending vending github.com/cbroglie/mustache/tree/master/cmd/mustache/vendor/… . Apakah GOPATH Anda disetel dengan benar?
VonC
Saya telah menemukan apa yang sudah Anda temukan. Paket ada dalam sub-direktori vendor: inilah mengapa paket tidak diinstal. Namun saya tidak tahu mengapa tidak menginstalnya sekarang di build. Atau bagaimana menggunakan direktori vendor (jika saya menyalinnya ke direktori saya).
ctrl-alt-delor