In my opinion, not allowing circular dependencies is a great design choice for building large programs. It forces you to separate your concerns properly.<p>If you get a circular dependency something is wrong with your design and the article does a good job on how to fix them.<p>I sometimes use function pointers which other packages override to fix circular dependencies which I don't think was mentioned in the article.<p>My only wish is that the go compiler gave more helpful output when you make a circular dependency. Currently it gives a list of all the packages involved in the loop which can be quite long, though generally it is the last thing you changed which caused the problem.
great blog post! also this website has a lot of incredible posts, if you like learning about functional programming, you should check out<p><a href="https://jerf.org/iri/blogbooks/functional-programming-lessons-in-imperative-code/" rel="nofollow">https://jerf.org/iri/blogbooks/functional-programming-lesson...</a>
One bonus technique related to the “move to a third package” advice: generating many of your model structures (SQL, Protobuf, graphql, etc) allows you to set up obvious directionality between generated layers and to provide all generated code as “base packages” to your application code, which then composes everything together.<p>Prior to this technique we often had “models importing models circularly” as an issue but that’s entirely disappeared due to the introduction of the structural additional layer.
A funny quirk about golang is you cannot have circular dependencies at the package level, but you can have circular dependencies in go.mod<p>The tl;dr is don't do that either.