Break up go project into subfolders

前端 未结 6 888
傲寒
傲寒 2020-12-30 01:18

I want to break my project up to subfolders.

I want this code structure:

├── main.go
└── models
    └── user.go

Where main.go is:

相关标签:
6条回答
  • 2020-12-30 01:37

    I recently achieved this by using go modules.

    Golang introduced preliminary opt-in support for modules as of go v1.11.1 which is intended to completely remove the, frankly, absurd $GOPATH necessity. Not only can you now have versioned dependencies in any normal directory such as ~/development, but you can basically have something that looks like namespaces and sub-directories. You can enable this feature by invoking the go command with the following environment variable: GO111MODULE=on.

    Go v1.11.3 expects to enable modules by default and is slated for August 2019.


    Here is an example directory structure (that you might find typically in some other languages).

    ~/Dev/my-app
     ├── src/
     │   ├── one/
     │   │   ├── two/
     │   │   │   └── two.go
     │   │   └── one.go
     │   └── zero.go
     ├── go.mod
     └── app.go
    

    The application is called my-app, which will be the module name for app.go. We define this once in go.mod and then each of all the other go files in subdirectories will automatically be importable as if they were namespaced.

    Given the above, two.go, assuming it contains a function named Two, will be importable in app.go by using my-app/src/one/two.

    Here's what you need to do to achieve this:

    go.mod

    module my-app
    

    two.go

    package two
    
    func Two() string {
        return "I'm totally not supposed to be using go modules for this"
    }
    

    app.go

    package main
    
    import "my-app/src/one/two"
    
    func main() {
        two.Two()
    }
    

    If you were to place another file within two/, then you would simply use two.TheNewFunc() as long as you made TheNewFunc() available within the new file.

    I created a very simple GitHub repo which you can check out as a demonstration.

    0 讨论(0)
  • 2020-12-30 01:40

    The packages are referenced in code in relation to your "go/src" folder

    └── go
        └── src
            └── myAwesomeProject
                ├── main.go
                └── models
                    └── user.go
    

    So in main.go

    package main
    
    import (
      "fmt"
      "myAwesomeProject/models"
    )
    

    Similarly packages can reference each other using the same convention.

    0 讨论(0)
  • 2020-12-30 01:48

    Your import should be an absolute one:

    import "github.com/abonec/go_import_problem/models"
    

    If you don't want to export your project to an external referential, you can do a:

    import "go_import_problem/models"
    

    (That is: "the name of your project folder accessible by GOPATH/your package")

    See "How to use custom packages in golang?".

    And you would use:

    models.User
    

    As mentioned in Effective Go:

    The importer of a package will use the name to refer to its contents, so exported names in the package can use that fact to avoid stutter.
    (Don't use the import . notation, which can simplify tests that must run outside the package they are testing, but should otherwise be avoided.)


    kostix adds in the comments:

    to reiterate, names of Go packages are always absolute (that is, there's no relative package names, neither with ./ nor with ../ or anything like that) but that names are "anchored" to one of the so-called workspaces listed in $GOPATH.

    When Go searches for a package, it looks through workspaces and tries to find a package in each of them, in order.
    The search is not recursive.
    And no, there's no requirement to encode URLs in package paths -- unless you want to make your package public.

    0 讨论(0)
  • 2020-12-30 01:48

    You should use your imported objects by it's imported names. For example if you

    import "./models"
    

    with struct User you should use it as

    models.User
    
    0 讨论(0)
  • 2020-12-30 01:54

    You need to qualify items in in a package by its package name

    So

    fmt.Println(models.User{"new_user"})
    
    0 讨论(0)
  • 2020-12-30 01:59

    Breaking up a single project into subfolders is not the recommended way of structuring a go project, which is why there is basically no good way to do what you want.

    If the project is really large, and too unwieldy to make a single package, consider splitting it into several totally distinct packages, rather than special sub-directory packages. This has the advantage of forcing you to think cleanly about your internal APIs.

    0 讨论(0)
提交回复
热议问题