Çok dosyalı bir Go projesi düzenleme [kapalı]


238

Not: Bu soru ile ilgilidir bu bir , ama iki yıl Git tarihinin çok uzun bir süredir.

Geliştirme sırasında bir Go projesini organize etmenin standart yolu nedir?

mypackProjem tek bir paket , bu yüzden sanırım tüm .go dosyalarını bir mypackdizine koydum .

Ama sonra, geliştirme sırasında test etmek istiyorum main, böylece paketi bildiren bir dosyaya ihtiyacım var , böylece yapabilirimgo run trypack.go

Bunu nasıl organize etmeliyim? Yapmam gerekiyor mu go install mypackbunu denemek istiyorum her zaman?


14
Bu kısa ekran harika: youtube.com/watch?v=XCsL89YtqCs
Matt

Bu , bir projenin paketlerle nasıl organize edileceğini anlamada başka bir yararlı bağlantıdır. Resmi Nasıl Yazılır Git Kodundan daha kolay olduğunu düşünüyorum.
IamNaN

Yeni Go modülleri sistemi için, bu cevap modül yapısını kapsar, bir modül içindeki paketleri düzenler, tek bir depoda birden fazla modül olsun ya da olmasın vs. Sonunda, modüller için resmi "Go Code Nasıl Yazılır " giriş belgesi güncellenecektir , ama henüz olmadı. (Go'da yeniyseniz ve Go modüllerinde yeniyseniz, modül belgelerinin çoğunda verilen modüller hakkında daha fazla bilgi okumadan önce "Go Code Nasıl Yazılır" belgesini okumaya değer.
Typic182

Yanıtlar:


171

Bu Kodu Nasıl Yazılır konusundaki incelemenizi tavsiye ederim

Hem projenizi go builddostça bir şekilde nasıl yapılandıracağınızı hem de testlerin nasıl yazılacağını belgeler . Testlerin mainpaketi kullanarak cmd olması gerekmez . Her paketin parçası olarak TestX olarak adlandırılmış işlevler olabilirler ve sonra go testbunları keşfederler.

Sorunuzdaki bu bağlantıda önerilen yapı, şimdi Go 1'in yayınlanmasıyla biraz modası geçmiş. Artık pkgaltına bir dizin yerleştirmeniz gerekmeyecek src. Spec ile ilgili 3 dizin sadece GOPATH kökündeki 3'tür: bin, pkg, src. mypackSrc'nin altına, projenizi yerleştirebilirsiniz ve bunun altında mypack_test.go dahil olmak üzere tüm .go dosyalarınızın altına yerleştirebilirsiniz.

go build daha sonra pkg ve bin kök seviyesine gelecek.

Yani GOPATH'iniz şöyle görünebilir:

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

export GOPATH=$HOME/projects

$ go build mypack
$ go test mypack

Güncelleme:> = Git 1.11'den itibaren , Modül sistemi artık takımın standart bir parçası ve GOPATH konsepti artık kullanılmıyor.


26
Değişkenleri dışa aktarırken ~ yerine $ HOME kullanın.
Johan S

6
Değişkenleri dışa aktarırken $ HOME neden ~ fazla öneriliyor?
425nesp

8
Çünkü ~ bir değişken değildir, sadece bir takma addır.
Pih

6
@ 425nesp Johan yanılıyor - değil. Kabuklar değişir, ancak çevresel değişkenleri ayarlarken bash genişler~ ve örneğin, meşgul kutusu bourne kabuğu da büyür. Kendiniz deneyin: export BOB=~ && env | grep ^BOBverecektirBOB=/your/homedir
Austin Adams

1
$HOMEo zaman daha fazla kabukta çalışır ~, örneğinfish
hoijui

60

jdi kullanımı ile ilgili doğru bilgilere sahiptir GOPATH. Ben de bir ikili olması istiyorsanız, dizinlere ek bir seviye eklemek isteyebilirsiniz ekleyebilirim.

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

çalışan go build myproj/mypackinşa edecek mypack's bağımlılıkları çalışan ile birlikte paket go build myproj/myappinşa edecek myappmuhtemelen içerir' s bağımlılıkları ile birlikte ikili mypackkütüphanesi.


Aslında bir ana cmd'si varsa, bu mantıklı olurdu. Sadece bir kütüphane paketi oluşturuyor gibi görünüyordu.
jdi

50

Çok sayıda Go projesi okudum ve oldukça fazla çeşitlilik var. C'nin kimden geldiğini ve Java'dan kimin geldiğini söyleyebilirsin, çünkü eski bir mainpaketin proje kök dizinindeki her şeyi döküyor ve ikincisi her şeyi birsrc dizine . Ancak her ikisi de optimal değildir. Her birinin sonuçları vardır, çünkü içe aktarma yollarını ve başkalarının bunları nasıl yeniden kullanabileceğini etkiler.

En iyi sonuçları almak için aşağıdaki yaklaşımı kullandım.

myproj/
  main/
    mypack.go
  mypack.go

Burada mypack.goolduğu package mypackve main/mypack.go(tabii ki) 'dirpackage main .

Ek destek dosyalarına ihtiyacınız varsa iki seçeneğiniz vardır. Hepsini kök dizinde tutun veya özel destek dosyalarını bir libalt dizine koyun . Örneğin

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

Veya

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

Dosyaları yalnızca libbaşka bir proje tarafından içe aktarılmaları amaçlanmadıysa bir dizine koyun . Başka bir deyişle, özel destek dosyalarıysa. Bu, libkamuyu özel arayüzlerden ayırmanın arkasındaki fikir .

İşleri bu şekilde yapmak myproj.org/mypack, kodu diğer projelerde yeniden kullanmanız için size güzel bir içe aktarma yolu verecektir . Kullanırsanız, libdahili destek dosyalarının bunu gösteren bir alma yolu olacaktır myproj.org/lib/mysupport.

Projeyi oluştururken main/mypack, örn go build main/mypack. Birden fazla çalıştırılabilir programınız varsa, mainayrı projeler oluşturmak zorunda kalmadan bunları da ayırabilirsiniz . örneğin main/myfoo/myfoo.gove main/mybar/mybar.go.


14
Idomatic, cmd/nameOfMyExecutableana paket için bir alt dizin kullanmaktır (sadece cmd/…birden fazla komutunuz varsa gerekir ; bkz golang.org/x/tools/cmd; aksi takdirde onu takas etmek ve main.goen üst düzeyde olmak yaygındır ). Sahip olduğunuz şekilde go installbir "ana" (veya "main.exe") yürütülebilir dosyası oluşturur. Ayrıca, idiomatic, internalbaşka bir yerde kullanılması amaçlanmayan pakete / programa dahil olan bir alt paket için bir alt-dizin kullanmaktır (Go'nun gelecekteki sürümlerinin, internalbu şekilde yapılan paketleri ithal eden başka kimseyi zorlamaması beklenmektedir ).
Dave C


13

Go projelerini organize etmenin standart bir yolu yoktur, ancak https://golang.org/doc/code.html çoğu proje için en iyi uygulamayı belirtir. jdi'nin cevabı iyidir, ancak github veya bitbucket kullanıyorsanız ve ek kitaplıklarınız varsa, aşağıdaki yapıyı oluşturmanız gerekir:

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

Bu şekilde mylib için diğer projeler için kullanılabilecek ve "git" ile alınabilecek ayrı bir havuzunuz olabilir. Mypack projeniz "github.com/username/mylib" adresini kullanarak kitaplığınızı içe aktarabilir. Daha fazla bilgi için:

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


6

Dosyaları aynı dizinde tutun ve package maintüm dosyalarda kullanın .

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

O zaman koş:

~/myproj/your-program$ go build && ./your-program

Bu nasıl çalışır? Main.go'nuzun ana paket olması gerekir; muhtemelen lib.go farklı bir pakette, o zaman go aracı tek bir klasörde iki pakete sahip olamayacağınızdan şikayet ediyor.
I82Much

1
@ I82Much OP, bir paketi, ana programı, birçok dosyaya nasıl böleceğinizi sorar. lib.go bu durumda aynı pakette.
Gustav

Ah açıklama için teşekkürler.
I82Much

@Gustav, aynı sorum var. Main.go içine main paketini koyarsam lib.go'da tanımlanan işlevleri çağıramam gibi görünüyor.
Qian Chen

@ElgsQianChen Yöntemlerin halka açık olması gerekir, büyük harfle başlamalıdır. Örneğin MyMethod () veya MyStruct {...}.
Gustav

6

go get repository_remote_urlKomutun proje yapısını nasıl yönettiğini keşfedelim $GOPATH. Eğer biz yaparsak go get github.com/gohugoio/hugodepoyu klonlayacaktır

$ GOPATH / src / depo_uzaktanı / kullanıcı_adı / proje_adı


GOPATH / src / github.com/gohugoio/hugo

Bu, ilk proje yolunuzu oluşturmanın güzel bir yoludur . Şimdi proje türlerinin neler olduğunu ve iç yapılarının nasıl düzenlendiğini inceleyelim. Topluluktaki tüm golang projeleri aşağıdaki kategorilere ayrılabilir:

  • Libraries (yürütülebilir ikili dosya yok)
  • Single Project (yalnızca 1 çalıştırılabilir ikili dosya içerir)
  • Tooling Projects (birden fazla yürütülebilir ikili dosya içerir)

Genellikle golang proje dosyaları DDD , POD gibi herhangi bir tasarım prensibi altında paketlenebilir

Mevcut go projelerinin çoğu bu Paket Odaklı Tasarımı takip eder

Paket Odaklı Tasarım , geliştiriciyi uygulamayı yalnızca kendi paketlerinde tutmaya teşvik eder, /internalbu paketlerin birbirleriyle iletişim kuramayacağı paket dışında


Kütüphaneler

  • Veritabanı sürücüleri , qt gibi projeler bu kategoriye konulabilir.
  • Gibi bazı kütüphaneler renk , şimdi başka paketler olmadan düz bir yapıyı izler.
  • Bu kütüphane projelerinin çoğu internal adlı bir paketi yönetir .
  • /internal paket esas olarak uygulamayı diğer projelerden gizlemek için kullanılır.
  • Yürütülebilir ikili dosyalara sahip olmadığınızdan, ana işlevi içeren hiçbir dosya yoktur .

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

Tek Proje

  • Hugo , vb gibi projelerin kök düzeyinde tek bir ana işlevi vardır .
  • Hedef tek bir ikili oluşturmaktır

Kalıp Projeleri

  • Kubernetes , go-ethereum gibi projelerin cmd adı verilen bir paket altında organize edilmiş birden fazla ana işlevi vardır
  • cmd/ paketi oluşturmak istediğimiz ikili dosyaların (araçların) sayısını yönetir

 ~/$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/
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.