I have read all kinds of articles covering this issue and there are a lot of different approaches out there. I'm new to Go and I'm trying to learn the best practices instead of picking up some bad styles right in the beginning.
Coming from languages that have classes, I'm trying not to apply everything I've learnt over the years when learning a new language like Go.
Which brings up my first point: Is it considered a good style in Go to structure you program in packages and folders?
From what I've read so far, some people recommend doing that, so I went for a structure like this (my actual program is much bigger and therefor qualifies for the 'move code to packages' approach):
.
├── bin
│ └── helloworld
└── src
├── github.com
│ ├── SOMEUSER
│ │ └── helloworld
│ │ ├── main.go
│ │ ├── main_test.go
│ │ ├── greeter
│ │ │ └── talker.go
│ │ └── person.go
So as you can see I moved some new code to a separate package which in this case would be greeter
. I import this package in my main.go file (I've read multiple times already that this approach is recommended instead of doing the import like import ./greeter
) :
package main
import "github.com/SOMEUSER/helloworld/greeter"
func main() {
greeter.Hello()
}
which then calls the function Hello()
in my greeter
package. So far so good.
But here comes my actual question (assuming that the above structure would be the recommended way to structure code in Go):
How can I now use any function, struct, etc. which was declared in any of the files in my main
package (here I have some serious doubts if this would be the way to go, no pun intended)?
So let's assume I declared some struct in person.go
called Person
. This struct is now used at several parts of my application, and it'd be good to also use it in my included (local) package, like this:
package greeter
import "fmt"
func Hello() {
p := Person{Name: "Steve"}
fmt.Println(p.Name)
}
When trying to build this, it throws an undefined: Person
error.
If you could point me in the right direction and enlighten me about the recommended way and style how this is approached in Go, I'd be very thankful.
To use the Person
struct, you would need to import the github.com/SOMEUSER/helloworld
package and use it like main.Person
. However, it isn't possible because you can't import a main
package and it would create a circular depedency.
Generally, I export into sub-packages the following code :
main
codeNow, keep in mind that it really is a question of complexity. Having many files but low complexity doesn't justify a subpackage.
There are two "solutions" here.
1) Put the code back in the main package until you know what to do with it (which is my recommendation)
2) Create a person package defining the Person type and import that package into both. I think person.Person is silly, which is why I wouldn't do this. database.Person or server.Person makes more sense to me. I mean at that point it all comes down to how you're reading, writing and storing Person, and that's unclear.