This bothers me from time to time. When I first started using Go, I think I complained to the Go team about it. They told me to think more carefully about where package boundaries are. Having the smallest package possible doesn't necessarily mean the design is good.
I inherited an app from a coworker, and he just put every file in the main package. This was actually fine and caused no problems.
These days, I still have an addiction to making tiny packages, which the Go team would likely not approve. But I'm a big girl and I do what I want! The workarounds I use are:
1) A `types` package. type Chicken struct { Children []Egg }; type Egg struct { Mom, Dad Chicken }.
2) A `utils` package. Let me explain. I would never name a package `utils`. That's illegal and I'm told that the compiler will explode into a thousand pieces if you try. All the king's horses and all the king's men wouldn't be able to put it back together again. So don't test it. Just trust me. But, you can definitely have something like `package hatchery` with a functions related to collecting eggs from chickens. Or you can have `package eggutil` for packing eggs, frying eggs, and shipping eggs.
I would say that I typically have a `types` package (called `types` if I'm hand-writing the code, or myapppb if it's protobufs like at Google), and then structure the rest of my app as model/view/controller. The model puts these types into the database. (Call it `eggdb`.) The controller does whatever business logic you care about (getting chickens together to fertilize eggs, call it `husbandry`). The view calls into the controller to implement your API / gRPC endpoint / beautiful Gtk+ GUI / whatever.
And then you don't really have problems with circular dependencies.
Having said all that if someone puts it all in main.go I'd probably approve the PR. The Go team let my coworker do it in 2014 and nobody died.
You’re not seeing the problem. You spend an inordinate amount of time trying to organize it and you come up with an elegant way so the catharsis of that solution makes you think you found the path to nirvana. Really you’ve been duped.
This restriction makes sense for packages. But not for folders. The problem arises in go because folders and packages are the same thing and that’s stupid because people don’t typically use folders as if they were packages. Folders are typically used just to categorize things of similar meaning or naming or whatever you want.
No other popular language has this issue. I can choose to organize things how I want in any other language. I have the freedom. I can make a folder A and B and C and D and just organize things in ABC order. But can’t with go. If I dont want to do this in any other language I have the option to create a package.
Creating a package and creating a folder are completely orthogonal tools and concepts and the genius who invented go just made a horrible design decision here.
> that’s stupid because people don’t typically use folders as if they were packages. Folders are typically used just to categorize things of similar meaning or naming or whatever you want
You might do that. That does not mean everyone organizes things like this.
What your chicken/egg example fails to realize is that things rarely just belong in one category. Chickens can be animals or food.
To me it just sounds like you are trying to write another language while using Go. Of course you will see problems. Just as you would see problems trying to write Go code when using Java.
In the end it comes down to this: if the language does not fit your mental model on how to do things, don't use it. But don't go around shitting on the language just because you are used to using folders differently than other people. Using a language also means learning and using the conventions of that language.
>You might do that. That does not mean everyone organizes things like this.
Most people do organize things arbitrarily based off of their own categorizations and opinions. In fact such an overwhelming majority of people who use operating systems do this that it's pretty much universal.
>What your chicken/egg example fails to realize is that things rarely just belong in one category. Chickens can be animals or food.
So what. I choose not to eat my chickens. So I Choose to categorize it in a way that makes sense to me. Why should I conform to your point of view? Why should I conform to golangs point of view? Why can't you and I choose how to do it?
>To me it just sounds like you are trying to write another language while using Go. Of course you will see problems. Just as you would see problems trying to write Go code when using Java.
No. I'm complaining about go. I think it's dumb. I'm not doing OOP here, I hate OOP. Go is waaay better. This is orthogonal to that problem.
>In the end it comes down to this: if the language does not fit your mental model on how to do things, don't use it. But don't go around shitting on the language just because you are used to using folders differently than other people. Using a language also means learning and using the conventions of that language.
Yeah that's how all complaints and criticisms are sidelined. "You don't like it, don't use it. Use something you like." Obviously.
I'm doing exactly that, while saying that go packages are a poor and horrible design decision.
I think a lot of people hated java, and found go and they think because go is so much better then java then that means go can do no wrong.
I don't think you realize there's stuff way better then go out there. But that's besides my point. What I use is separate from my point: Golang packages are poorly designed.
> I don't think you realize there's stuff way better then go out there.
Every language makes trade-offs. For you the trade-off Go makes is bad. I disagree. I like some languages better in certain parts, while I prefer Go's solution in other parts. It's all preference, there is almost never an objective "better" or "worse" like you seem to think.
Then you disagree with the majority of people. That's my point. This agree/disagree side lines the fact that people can be right or wrong. My claim is not only do you disagree, but you're wrong.
Majority of what people? Get off your high horse, your opinion is not a fact. Give me objective metrics to measure how "good" a language or language feature is, otherwise you are just wrong.
I'm looking forward to trying out your own perfect language that is objectively the best for any use case ever and no one can find any faults with it. Because surely such a language exists.
>Majority of what people? Get off your high horse, your opinion is not a fact.
Just look at reality and how people organize things everywhere. It's arbitrary. Adults are placed in offices and kids are placed in schools. Then on family trees kids and Adults are organized by dependency. How people organize things in the REAL world is AN arbitrary choice. But in GO you have NO CHOICE. It has to be by family tree. That is NOT an opinion. Everything I said is FACT.
The metric is basically the entire world and everything in it and how we fundamentally type (aka organize) things within it. But if you want to get more specific just look at every other programming language except go and look at how the entire world uses folders in operating systems. These are tools to allow people to arbitrarily organize things.
>I'm looking forward to trying out your own perfect language that is objectively the best for any use case ever and no one can find any faults with it. Because surely such a language exists.
Don't have one. I'm just commenting on what I hate about golang.
So a hand-wavy "look at the world bro" instead of actual metrics. Got it.
> I'm just commenting on what I hate about golang.
No you're not. You say Go (or a part of Go) is bad, which is vastly different. If you stuck to "I don't like it", you would not have gotten so much push back, but you insist in being right and everyone else is stupid and wrong.
Because metrics don’t exist. If the only way you can move forward and know something is because someone conducted some sort of statistical experiment with data analysis on it then I don’t even know how you get up in the morning. Do you need science to prove that when you jump off the bed there’s a floor that your feet will land on?
No you don’t. You’re not an idiot. It’s common sense that allows you to do this and it’s common sense that will allow you to see that the entire world works the way I said it does above. You don’t need science for this. At least most people don’t. Maybe you’re different and you need science to do an analysis for you before you open any door to make sure reality still exists behind it.
> No you're not. You say Go (or a part of Go) is bad, which is vastly different. If you stuck to "I don't like it", you would not have gotten so much push back, but you insist in being right and everyone else is stupid and wrong.
You’re right. Let me rephrase what I meant. I’m commenting about what is fundamentally terrible about golang and if you disagree then you're wrong because the overwhelming majority of the world would disagree.
> You spend an inordinate amount of time trying to organize it
I mean, I don't. I've been doing Go for well over 10 years, so I'm well aware of the limitation and intentionally avoid running into it. "Well I hate that!" Yeah, we know. What can you do about it? Use something else.
In a past life, I taught Perl classes at companies that use Perl. One time I was explaining the advanced parts of @INC (the module lookup configuration/resolution order variable). One student hated it to the point of tears. They could not live with a programming language that had an @INC variable. Nothing I can do about that. It does. Get over it, or don't get over it. Those are the only two options.
I inherited an app from a coworker, and he just put every file in the main package. This was actually fine and caused no problems.
These days, I still have an addiction to making tiny packages, which the Go team would likely not approve. But I'm a big girl and I do what I want! The workarounds I use are:
1) A `types` package. type Chicken struct { Children []Egg }; type Egg struct { Mom, Dad Chicken }.
2) A `utils` package. Let me explain. I would never name a package `utils`. That's illegal and I'm told that the compiler will explode into a thousand pieces if you try. All the king's horses and all the king's men wouldn't be able to put it back together again. So don't test it. Just trust me. But, you can definitely have something like `package hatchery` with a functions related to collecting eggs from chickens. Or you can have `package eggutil` for packing eggs, frying eggs, and shipping eggs.
I would say that I typically have a `types` package (called `types` if I'm hand-writing the code, or myapppb if it's protobufs like at Google), and then structure the rest of my app as model/view/controller. The model puts these types into the database. (Call it `eggdb`.) The controller does whatever business logic you care about (getting chickens together to fertilize eggs, call it `husbandry`). The view calls into the controller to implement your API / gRPC endpoint / beautiful Gtk+ GUI / whatever.
And then you don't really have problems with circular dependencies.
Having said all that if someone puts it all in main.go I'd probably approve the PR. The Go team let my coworker do it in 2014 and nobody died.