Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: allow import cycle #30247

Closed
minkofski opened this issue Feb 15, 2019 · 5 comments
Closed

proposal: Go 2: allow import cycle #30247

minkofski opened this issue Feb 15, 2019 · 5 comments

Comments

@minkofski
Copy link

minkofski commented Feb 15, 2019

I understand that disallow import cycle is intentional in Go design.
However, solving the import cycle issue makes me frustrated.
And, it is easy to write two coupling components that rely on each other

  • Although we can use interface can address the issue, it decreases the readability since a developer must carefully read the source to find out which instance is represented by the interface (abuse of interface).
  • There are many Go standard package rely on runtime private calls and uses go:linkname to address the import cycle problem. However, it is still a hack and not recommended by the Go team.

I believe many people encounter import cycle issue and spend time on code refactoring, which is good, but this is unforgivable in business logic development sometimes.

Concern: How much compile time will be sacrificed while introducing dependency analysis? Is there any recent research advances for rapid dependency analysis can be integrated?

@gopherbot gopherbot added this to the Proposal milestone Feb 15, 2019
@robpike
Copy link
Contributor

robpike commented Feb 15, 2019

The lack of import cycles in Go forces programmers to think more about their dependencies and keep the dependency graph clean and builds fast. Conversely, allowing cycles enables laziness, poor dependency management, and slow builds. Eventually one ends up with a single cyclical blob enclosing the entire dependency graph and forcing it into a single build object. This is very bad for build performance and dependency resolution. These blobs are also take much more work to detangle than the is required to keep the graph a proper DAG in the first place.

This is one area where up-front simplicity is worthwhile.

Import cycles can be convenient but their cost can be catastrophic. They should continue to be disallowed.

@minkofski
Copy link
Author

@robpike Indeed, import cycle is dangerous, double-edged sword.
It depends on how Go team decide it should be. Go users like the simplicity of Go, but spend time on things they have ever enchanted before, for instance, error handling (well, off topic).

I don't know it is possible to formal prove any projects written in Go can be designed without import cycle, at least Go source is a counter example that requires import cycles in many places.

This proposal is opened for discussion. People who watch this repo have sophisticated experience in Go, their opinion are biased sometimes (not criticize), and definitely understand what are best practices in dependency management. Unfortunately, not everyone can be.

I wish Go team and people who contributes to Go could discuss for the balance of allowability of import cycles, for instance, allow import cycle under few restrict criteria, which allows build fast as well as clean dependency.

@go101
Copy link

go101 commented Feb 15, 2019

Disabling import cycles really causes some conveniences sometimes, but enabling import cycles will cause confusions. When I began using C++, I often encountered compilation errors caused by import cycles. Surely, I learned to always use pointers to avoid the compilation errors caused by import cycles. But, as a C++ beginner, it was really a frustrating experience.

With introducing modules, enabling import cycles may cause a package to depend another version of the package easily. For example, assume foo.com/lib and bar.com/pkg depend on each other, when foo.com/lib is upgraded to a new version, the new version will depend on one of its old version.

@mlevieux
Copy link
Contributor

A while ago I started a thread on go-nuts about that. My feeling (which is really intuitive I must confess) is that our brain naturally thinks circularly sometimes. Being able to conciliate the way our thoughts build themselves and the way we can build a program using our favorite language is (again, much intuitively) a good thing in my opinion.

However, along this discussion we've had with part of the Go community brought many arguments against allowing import cycles. For me the most decisive argument is that as much as I have about it since then, I haven't been able to formulate a clear, concise, simple case where it is NOT possible to think your types / packages without import cycles. I'll get even further with this, I have not been able to find a single case where it is clearer (in terms of maintenance or understanding) and fundamentally more logical to use import cycles. Therefore I have found my way to thinking that maybe, where one thinks that import cycles are necessary, the real, underlying problem is probably that the way the project has been thought and built is not the right one, from the beginning, and that the project most probably needs rethinking / refactoring.

Rob Pike's argument is also for me a really interesting one. It is easy to right bad code, and making it easier might not be the solution to any of our problems.

I don't know of a real "study" that would have been made to dig deeper into this dividing question, but I personally think that if such a research exists, it clearly does not reach the conclusion that import cycles are a good thing. After that, I still don't know if an optimal, beautiful solution will someday be discovered / invented.

Just to state my opinion now, after having thought about this for quite a long time, and in the light of all the arguments for / against imports cycles, I don't want them in Go anymore.

@ianlancetaylor
Copy link
Contributor

Sorry, this kind of change simply isn't going to happen.

Note that while the Go standard library uses go:linkname more than is ideal, it is rarely, perhaps never, done to avoid import cycles. It's done to avoid exporting APIs that shouldn't be public.

If you want to discuss this further, I recommend doing so on the golang-nuts mailing list.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants