Mengatur proyek multi-file Go [ditutup]

238

Catatan: pertanyaan ini terkait dengan yang satu ini , tetapi dua tahun adalah waktu yang sangat lama dalam sejarah Go.

Apa cara standar untuk mengatur proyek Go selama pengembangan?

Proyek saya adalah satu paket mypack, jadi saya kira saya meletakkan semua file .go di mypackdirektori.

Tapi kemudian, saya ingin mengujinya selama pengembangan sehingga saya membutuhkan setidaknya file yang menyatakan mainpaket, sehingga saya bisa melakukannyago run trypack.go

Bagaimana saya mengaturnya? Apakah saya perlu melakukannya go install mypacksetiap kali ingin mencobanya?

Blacksad
sumber
14
Screencast singkat ini luar biasa: youtube.com/watch?v=XCsL89YtqCs
Matt
Ini adalah tautan bermanfaat lainnya dalam memahami bagaimana mengatur proyek dengan paket. Lebih mudah diikuti daripada resmi. Bagaimana menurut saya.
IamNaN
Untuk sistem modul Go yang baru, jawaban ini mencakup struktur modul, mengatur paket dalam suatu modul, apakah memiliki beberapa modul dalam repositori tunggal atau tidak, dll. Pada akhirnya, dokumen intro resmi "Cara Menulis Kode Go" akan diperbarui untuk modul , tapi itu belum terjadi. (Jika Anda baru untuk Go dan modul Go to, masih perlu dibaca bahwa dokumen "Bagaimana Menulis Kode Go" sebelum membaca lebih lanjut tentang modul mengingat sebagian besar dokumentasi modul mengasumsikan keakraban dengan GOPATH).
typical182

Jawaban:

171

Saya akan merekomendasikan meninjau halaman ini tentang Cara Menulis Kode Pergi

Ini mendokumentasikan baik bagaimana menyusun proyek Anda dengan go buildcara yang ramah, dan juga bagaimana menulis tes. Tes tidak perlu cmd menggunakan mainpaket. Mereka hanya bisa menjadi fungsi bernama TestX sebagai bagian dari setiap paket, dan kemudian go testakan menemukannya.

Struktur yang disarankan dalam tautan itu dalam pertanyaan Anda agak ketinggalan jaman, sekarang dengan rilis Go 1. Anda tidak lagi perlu menempatkan pkgdirektori di bawah src. Hanya 3 direktori yang berhubungan dengan spesifikasi adalah 3 di root GOPATH Anda: bin, pkg, src. Di bawah src, Anda cukup menempatkan proyek Anda mypack, dan di bawahnya semua file .go Anda termasuk mypack_test.go

go build kemudian akan membangun pkg dan bin level root.

Jadi GOPATH Anda mungkin terlihat seperti ini:

~/projects/
    bin/
    pkg/
    src/
      mypack/
        foo.go
        bar.go
        mypack_test.go

export GOPATH=$HOME/projects

$ go build mypack
$ go test mypack

Pembaruan: pada> = Go 1.11, sistem Modul sekarang menjadi bagian standar dari perkakas dan konsep GOPATH hampir menjadi usang.

jdi
sumber
26
Gunakan $ HOME daripada ~ saat mengekspor variabel.
Johan S
6
Mengapa $ HOME direkomendasikan lebih dari ~ saat mengekspor variabel?
425nesp
8
Karena ~ bukan variabel, hanya sebuah alias.
Pih
6
@ 425nesp Johan salah - tidak. Shell berbeda-beda, tetapi bash mengembang ~ketika mengatur variabel lingkungan , dan begitu pula shell bourne busybox, misalnya. Cobalah sendiri: export BOB=~ && env | grep ^BOBakan menghasilkanBOB=/your/homedir
Austin Adams
1
$HOMEbekerja di lebih banyak kerang kemudian ~, misalnya difish
hoijui
60

jdi memiliki informasi yang benar mengenai penggunaan GOPATH. Saya akan menambahkan bahwa jika Anda berniat untuk memiliki biner juga, Anda mungkin ingin menambahkan satu level tambahan ke direktori.

~/projects/src/
    myproj/
        mypack/
            lib.go
            lib_test.go
            ...
        myapp/
            main.go

running go build myproj/mypackakan membangun mypackpaket beserta dependensinya menjalankan, go build myproj/myappakan membangun myappbiner beserta dependensinya yang mungkin termasuk mypackpustaka.

Jeremy Wall
sumber
Ini akan masuk akal, tentu saja, jika dia benar-benar memiliki cmd utama. Sepertinya dia baru saja membuat paket perpustakaan.
jdi
50

Saya telah mempelajari sejumlah proyek Go dan ada sedikit variasi. Anda dapat memberi tahu siapa yang datang dari C dan siapa yang datang dari Jawa, karena mantan membuang hampir semua yang ada di direktori root proyek dalam sebuah mainpaket, dan yang terakhir cenderung untuk meletakkan semuanya di srcdirektori. Namun tidak ada yang optimal. Masing-masing memiliki konsekuensi karena mereka memengaruhi jalur impor dan bagaimana orang lain dapat menggunakannya kembali.

Untuk mendapatkan hasil terbaik saya telah mengerjakan pendekatan berikut.

myproj/
  main/
    mypack.go
  mypack.go

Di mana mypack.goadalah package mypackdan main/mypack.go(jelas) package main.

Jika Anda memerlukan file dukungan tambahan, Anda memiliki dua pilihan. Simpan semuanya di direktori root, atau letakkan file dukungan pribadi di libsubdirektori. Misalnya

myproj/
  main/
    mypack.go
  myextras/
    someextra.go
  mypack.go
  mysupport.go

Atau

myproj.org/
  lib/
    mysupport.go
    myextras/
      someextra.go
  main/
    mypack.go
  mypage.go

Hanya masukkan file dalam libdirektori jika tidak dimaksudkan untuk diimpor oleh proyek lain. Dengan kata lain, jika itu file pendukung pribadi . Itulah ide di balik memiliki lib- untuk memisahkan publik dari antarmuka pribadi.

Melakukan hal-hal seperti ini akan memberi Anda jalur impor yang bagus, myproj.org/mypackuntuk menggunakan kembali kode dalam proyek lain. Jika Anda menggunakan libmaka file dukungan internal akan memiliki jalur impor yang menunjukkan itu myproj.org/lib/mysupport,.

Saat membangun proyek, gunakan main/mypack, misalnya go build main/mypack. Jika Anda memiliki lebih dari satu yang dapat dieksekusi, Anda juga dapat memisahkannya di bawah maintanpa harus membuat proyek terpisah. misalnya main/myfoo/myfoo.godan main/mybar/mybar.go.

trans
sumber
14
Idomatic adalah dengan menggunakan cmd/nameOfMyExecutablesub-direktori untuk paket utama (hanya perlu cmd/…jika Anda memiliki banyak perintah; lihat golang.org/x/tools/cmd; jika tidak, itu umum untuk bertukar sekitar dan ada main.godi tingkat atas). Cara Anda memilikinya go installakan membuat executable "main" (atau "main.exe"). Juga, idiomatic adalah menggunakan internalsub-direktori untuk sub-paket internal ke paket / program yang tidak dimaksudkan untuk digunakan di tempat lain (diharapkan versi Go di masa depan akan memberlakukan tidak ada orang lain yang mengimpor internalpaket yang dilakukan dengan cara ini).
Dave C
21

Saya merasa sangat berguna untuk memahami bagaimana mengatur kode di Golang bab ini http://www.golang-book.com/11 dari buku yang ditulis oleh Caleb Doxsey

edap
sumber
13

Tampaknya tidak ada cara standar untuk mengatur proyek Go tetapi https://golang.org/doc/code.html menetapkan praktik terbaik untuk sebagian besar proyek. Jawaban jdi baik tetapi jika Anda menggunakan github atau bitbucket dan Anda memiliki perpustakaan tambahan juga, Anda harus membuat struktur berikut:

~/projects/
bin/
pkg/
src/
  github.com/
    username/
        mypack/
            foo.go
            bar.go
            mypack_test.go
        mylib/
            utillib.go
            utillib_test.go

Dengan melakukannya dengan cara ini, Anda dapat memiliki repositori terpisah untuk mylib yang dapat digunakan untuk proyek lain dan dapat diambil dengan "go get". Proyek mypack Anda dapat mengimpor perpustakaan Anda menggunakan "github.com/username/mylib". Untuk informasi lebih lanjut:

http://www.alexvictorchan.com/2014/11/06/go-project-structure/

alexdotc
sumber
6

Simpan file dalam direktori yang sama dan gunakan package maindi semua file.

myproj/
   your-program/
      main.go
      lib.go

Lalu lari:

~/myproj/your-program$ go build && ./your-program
Gustav
sumber
1
Bagaimana ini bisa berhasil? Main.go Anda harus menjadi paket utama; mungkin lib.go ada dalam paket yang berbeda, maka alat go mengeluh bahwa Anda tidak dapat memiliki dua paket dalam satu folder.
I82Much
1
@ I82Much OP menanyakan cara membagi satu paket, program utama, ke banyak file. lib.go ada dalam paket yang sama dalam hal ini.
Gustav
Ah terima kasih atas klarifikasi.
I82Much
@ Gustav, saya punya pertanyaan yang sama. Sepertinya saya meletakkan paket utama di lib.go, di main.go, saya tidak bisa memanggil fungsi yang didefinisikan di lib.go.
Qian Chen
@ ElgsQianChen Metode harus publik, harus dimulai dengan huruf kapital. Misalnya MyMethod () atau MyStruct {...}.
Gustav
6

Mari kita menjelajahi bagaimana go get repository_remote_urlperintah mengelola struktur proyek di bawah $GOPATH. Jika kita lakukan, go get github.com/gohugoio/hugoitu akan mengkloning repositori di bawah

$ GOPATH / src / repository_remote / user_name / project_name


$ GOPATH / src / github.com/gohugoio/hugo

Ini adalah cara yang bagus untuk membuat jalur proyek awal Anda . Sekarang mari kita menjelajahi apa jenis proyek di luar sana dan bagaimana struktur bagian dalamnya diorganisir. Semua proyek golang di komunitas dapat dikategorikan dalam

  • Libraries (tidak ada binari yang dapat dieksekusi)
  • Single Project (hanya mengandung 1 biner yang dapat dieksekusi)
  • Tooling Projects (mengandung beberapa binari yang dapat dieksekusi)

Umumnya file proyek golang dapat dikemas dalam prinsip desain seperti DDD , POD

Sebagian besar proyek go yang tersedia mengikuti Desain Berorientasi Paket ini

Desain Berorientasi Paket mendorong pengembang untuk menjaga implementasi hanya di dalam paket itu sendiri, selain /internalpaket paket-paket itu tidak dapat berkomunikasi satu sama lain


Perpustakaan

  • Proyek-proyek seperti driver database , qt dapat dimasukkan ke dalam kategori ini.
  • Beberapa perpustakaan seperti warna , sekarang mengikuti struktur datar tanpa paket lain.
  • Sebagian besar proyek perpustakaan ini mengelola paket yang disebut internal .
  • /internal Paket ini terutama digunakan untuk menyembunyikan implementasi dari proyek lain.
  • Tidak memiliki binari yang dapat dieksekusi, jadi tidak ada file yang berisi fungsi utama .

 ~/$GOPATH/
    bin/
    pkg/
    src/
      repository_remote/
        user_name/
            project_name/
              internal/
              other_pkg/

Proyek tunggal

  • Proyek seperti hugo , etcd memiliki fungsi utama tunggal di tingkat root dan.
  • Target adalah untuk menghasilkan satu biner tunggal

Proyek Perkakas

  • Proyek-proyek seperti kubernetes , go-ethereum memiliki beberapa fungsi utama yang diatur di bawah paket yang disebut cmd
  • cmd/ paket mengatur jumlah binari (alat) yang ingin kita bangun

 ~/$GOPATH/
    bin/
    pkg/
    src/
      repository_remote/
        user_name/
            project_name/
              cmd/
                binary_one/
                   main.go
                binary_two/
                   main.go
                binary_three/
                   main.go
              other_pkg/
noelyahan
sumber