다중 파일 Go 프로젝트 구성 [닫기]


238

참고 :이 질문은 이것과 관련 있지만 Go 역사에서 2 년은 매우 오랜 시간입니다.

개발 중에 Go 프로젝트를 구성하는 표준 방법은 무엇입니까?

내 프로젝트는 단일 패키지 mypack이므로 모든 .go 파일을 mypack디렉토리 에 넣은 것 같습니다 .

그러나 개발 중에 테스트하고 싶기 때문에 main패키지를 선언하는 파일이 적어도 필요 하므로 할 수 있습니다.go run trypack.go

이것을 어떻게 구성해야합니까? go install mypack시도하고 싶을 때마다 해야 합니까?


14
이 간단한 스크린 캐스트는 굉장합니다 : youtube.com/watch?v=XCsL89YtqCs
Matt

패키지 프로젝트를 구성하는 방법을 이해하는 또 다른 유용한 링크입니다. 공식 코드 작성법보다 따르기 쉽다고 생각합니다.
IamNaN

새로운 Go 모듈 시스템의 경우이 답변 은 모듈 구조, 단일 저장소에 여러 모듈이 있는지 여부 등 모듈 내에 패키지를 배열하는 등의 내용을 다룹니다. 결국 모듈에 대한 공식 "Go Go 작성 방법" 소개 문서가 업데이트됩니다. 그러나 아직 일어나지 않았습니다. Go를 처음 사용하거나 Go를 처음 사용하는 경우에도 많은 모듈 설명서에서 GOPATH에 익숙하다고 가정하면 모듈에 대한 자세한 내용을 읽기 전에 "Go Code 작성 방법"문서를 읽어보십시오.
전형적인 182

답변:


171

Go 코드 작성 방법 에서이 페이지를 검토하는 것이 좋습니다.

go build친숙한 방식으로 프로젝트를 구성하는 방법과 테스트 작성 방법을 모두 설명합니다 . 테스트는 main패키지를 사용하는 cmd 일 필요는 없습니다 . 각 패키지의 일부로 간단히 TestX 명명 된 함수가 될 수 있으며, go test이를 발견 할 것입니다.

귀하의 질문에 해당 링크에서 제안 된 구조는 Go 1의 릴리스와 함께 약간 구식입니다. 더 이상 pkg아래 에 디렉토리 를 배치 할 필요가 없습니다 src. 3 개의 스펙 관련 디렉토리는 GOPATH 루트에있는 3 개 (bin, pkg, src)입니다. src 아래에 간단하게 프로젝트를 배치 할 수 mypack있으며 그 아래에는 mypack_test.go를 포함한 모든 .go 파일이 있습니다.

go build 그런 다음 루트 레벨 pkg 및 bin에 빌드됩니다.

따라서 GOPATH는 다음과 같습니다.

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

export GOPATH=$HOME/projects

$ go build mypack
$ go test mypack

업데이트 :> = Go 1.11 기준으로, 모듈 시스템은 이제 툴링의 표준 부분이며 GOPATH 개념은 더 이상 사용되지 않습니다.


26
변수를 내보낼 때는 ~ 대신 $ HOME을 사용하십시오.
Johan S

6
변수를 내보낼 때 $ HOME이 ~보다 권장되는 이유는 무엇입니까?
425nesp

8
~는 변수가 아니기 때문에 별칭 일뿐입니다.
Pih

6
@ 425nesp Johan은 착각했습니다. 쉘은 다양하지만 환경 변수를 설정할 때 bash가 확장~ 되므로 busybox bourne 쉘도 마찬가지입니다. 직접 해보기 : export BOB=~ && env | grep ^BOB생산량BOB=/your/homedir
Austin Adams

1
$HOME다음 더 쉘에서 작동 ~예를 들면,fish
hoijui

60

jdi는의 사용에 관한 올바른 정보를 가지고 있습니다 GOPATH. 바이너리를 가지고 싶다면 디렉토리에 하나의 레벨을 추가하고 싶을 것입니다.

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

running go build myproj/mypackmypack의존성과 함께 패키지를 빌드합니다. running go build myproj/myappmyapp아마도 mypack라이브러리를 포함하는 의존성과 함께 바이너리를 빌드합니다 .


물론 그가 실제로 주 cmd를 가지고 있다면 이것은 의미가 있습니다. 그가 단지 라이브러리 패키지를 만드는 것처럼 보였다.
jdi

50

나는 많은 Go 프로젝트를 연구했으며 약간의 변형이 있습니다. C에서 온 사람과 Java에서 온 사람을 알 수 있습니다. 전자는 main패키지 의 프로젝트 루트 디렉토리에있는 모든 것을 덤프 하고 후자는 src디렉토리 에 모든 것을 넣는 경향이 있습니다. 그러나 어느 쪽도 최적이 아닙니다. 각각 수입 경로에 영향을 미치고 다른 사람들이 재사용 경로에 영향을 미치기 때문에 결과가 발생합니다.

최상의 결과를 얻으려면 다음 방법을 사용했습니다.

myproj/
  main/
    mypack.go
  mypack.go

어디 mypack.go있다 package mypackmain/mypack.go(분명히)입니다 package main.

추가 지원 파일이 필요한 경우 두 가지 중에서 선택할 수 있습니다. 이들을 모두 루트 디렉토리에 보관하거나 개인 지원 파일을 lib서브 디렉토리 에 두십시오 . 예 :

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

또는

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

lib다른 프로젝트 에서 파일을 가져 오지 않을 경우에만 디렉토리에 파일을 넣으십시오 . 즉, 개인 지원 파일 인 경우입니다. lib개인 인터페이스와 공개를 분리 해야한다는 아이디어 입니다.

이런 식으로 작업하면 myproj.org/mypack다른 프로젝트에서 코드를 재사용 할 수있는 멋진 가져 오기 경로를 얻을 수 있습니다. lib내부 지원 파일 을 사용하는 경우이를 나타내는 가져 오기 경로가 myproj.org/lib/mysupport있습니다.

프로젝트를 빌드 할 때는을 사용하십시오 main/mypack(예 :) go build main/mypack. 실행 파일이 둘 이상인 경우 main별도의 프로젝트를 만들지 않고도 아래에서 실행 파일을 분리 할 수 ​​있습니다 . 예를 들어 main/myfoo/myfoo.gomain/mybar/mybar.go.


14
Idomatic은 cmd/nameOfMyExecutable메인 패키지 의 하위 디렉토리 를 사용하는 cmd/…것입니다 (여러 명령이있는 경우 에만 필요 합니다 golang.org/x/tools/cmd. 그렇지 않으면 참조하십시오 main.go. 이 방법으로 go install"main"(또는 "main.exe") 실행 파일을 만듭니다. 또한 관용구는 internal다른 곳에서 사용되지 않는 패키지 / 프로그램 내부의 하위 패키지에 하위 디렉토리 를 사용하는 것입니다 (Go의 향후 버전에서는 아무도 internal이런 방식으로 패키지를 가져 오지 않을 것으로 예상됩니다 ).
Dave C


13

Go 프로젝트를 구성하는 표준 방법은 없지만 https://golang.org/doc/code.html 은 대부분의 프로젝트에 대한 모범 사례를 지정합니다. jdi의 대답은 좋지만 github 또는 bitbucket을 사용하고 추가 라이브러리가있는 경우 다음 구조를 만들어야합니다.

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

이 방법으로 다른 프로젝트에 사용할 수 있고 "go get"으로 검색 할 수있는 mylib에 대한 별도의 저장소를 가질 수 있습니다. mypack 프로젝트는 "github.com/username/mylib"를 사용하여 라이브러리를 가져올 수 있습니다. 자세한 내용은:

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


6

파일을 동일한 디렉토리에 유지하고 package main모든 파일에서 사용 하십시오.

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

그런 다음 다음을 실행하십시오.

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

어떻게 작동합니까? main.go는 main 패키지 여야합니다. 아마도 lib.go는 다른 패키지에 있고 go 도구는 단일 폴더에 두 개의 패키지를 가질 수 없다고 불평합니다.
I82 많은

1
@ I82 많은 OP가 메인 프로그램 인 하나의 패키지를 여러 파일로 나누는 방법을 묻습니다. 이 경우 lib.go는 동일한 패키지에 있습니다.
구스타프

아, 설명해 주셔서 감사합니다.
I822018 년

@ 구스타프, 나는 같은 질문이 있습니다. lib.go, main.go에 패키지 main을 넣으면 lib.go에 정의 된 함수를 호출 할 수없는 것 같습니다.
Qian Chen

@ElgsQianChen이 메소드는 공개되어야하며 대문자로 시작해야합니다. 예 : MyMethod () 또는 MyStruct {...}.
구스타프

6

go get repository_remote_url아래 에서 명령이 프로젝트 구조를 관리하는 방법을 살펴 보겠습니다 $GOPATH. 우리가 go get github.com/gohugoio/hugo하면 저장소를 복제합니다.

$ GOPATH / src / repository_remote / user_name / project_name


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

이것은 초기 프로젝트 경로 를 만드는 좋은 방법 입니다. 이제 프로젝트 유형이 무엇이고 내부 구조가 어떻게 구성되어 있는지 탐험 해 봅시다. 커뮤니티의 모든 golang 프로젝트는 다음과 같이 분류 될 수 있습니다.

  • Libraries (실행 가능한 바이너리 없음)
  • Single Project (1 개의 실행 바이너리 만 포함)
  • Tooling Projects (여러 개의 실행 가능한 바이너리가 포함되어 있음)

일반적으로 golang 프로젝트 파일은 DDD , POD 와 같은 디자인 원칙에 따라 패키지 될 수 있습니다.

사용 가능한 대부분의 이동 프로젝트는이 패키지 지향 디자인을 따릅니다.

패키지 지향 디자인 은 개발자가 /internal패키지가 서로 통신 할 수없는 패키지 이외의 자체 패키지 내부에서만 구현을 유지하도록 권장합니다.


도서관

  • 데이터베이스 드라이버 , qt 와 같은 프로젝트 는이 범주에 속할 수 있습니다.
  • color 와 같은 일부 라이브러리 는 이제 다른 패키지없이 평평한 구조를 따릅니다.
  • 이러한 대부분의 라이브러리 프로젝트는 internal 이라는 패키지를 관리합니다 .
  • /internal package는 주로 다른 프로젝트에서 구현을 숨기는 데 사용됩니다.
  • 실행 가능한 바이너리가 없으므로 기본 func 가 포함 된 파일이 없습니다 .

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

단일 프로젝트

  • 이러한 프로젝트는 다음과 같이 휴고 , etcd하나의 루트 수준 및 주요 FUNC를.
  • 목표는 하나의 이진을 생성하는 것입니다

툴링 프로젝트

  • 같은 프로젝트 는 Kubernetes는 , 이동 - 에테 리움이 가지고 여러 패키지라고 아래에 구성 주요 FUNC cmd를
  • cmd/ package는 빌드하려는 바이너리 (도구)의 수를 관리합니다

 ~/$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/
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.