The only case where you can reasonably say that there are "two versions of the same package" in a build, is if they are in different major versions of the same module¹, say example.com/foo/v2 and example.com/foo/v3. In that context, you have control over both versions. You can guarantee that they use the same mutex, by having them refer to each other. That is, you would implement v2 in terms of v3, that way ensuring that even if some code still imports v2, they still ultimately use the v3 mutex. However, there is a problem: You can only implement v2 in terms of v3, once that exists. So you might introduce v3 while v2.23 is out and then have to introduce v2.24 to be implemented in terms of v3. But some clients might still import an v2.23. If those builds than *also* add v3, you end up with two mutexes. The way around that is to have both of those refer to a third package, which contains the mutex. So you would have example.com/internal/mutex (which lives in its own module example.com/internal) which contains a mutex and have example.com/foo/v2@v2.24 import that to refer to the mutex. You can then wait until all importers have upgraded to v2.24. And when you then build example.com/foo/v3, it also imports example.com/internal/mutex. That way, all builds use a single mutex. Of course, there is still a rest risk of clients not upgrading from v2.23 at all. But unfortunately, if you can't *somehow* prepare the earlier version and rely on that preparation to propagate, you are out of luck, I believe.
I don't believe there is a trick to statically enforce that two packages can not be imported at the same time (neither in the general case, nor in the special case that they are in two major versions of the same module). In a way, that's by design. It would be undesirable, for the import of one package to be able to break the import of a different package. Because if you *could* get into a situation where package A and package B are mutually exclusive, you could have a module dependency graph E->C->A, E->D->B and then the author of module E could do nothing to fix their build (as they can not force the authors of either module C or module D to change their imports, in a timely manner). Preventing these kinds of situations was a major design goal of Go modules. Which is why it's possible to use two major versions of a module in the same build in the first place. You could potentially dynamically enforce that there are no two major versions of the same module used in one build. A simple (somewhat limited) way would be to use `runtime/debug.BuildInfo` to check which modules are included in an `init` function and panic/exit if there is a conflict. But I would strongly warn against that. Because as I said, making this impossible statically was done for a reason and those reasons still apply if you do it dynamically - just that it's even more frustrating, because you will only notice *after* building and potentially deploying the binary. So, I think the real advice is: Don't. Do not rely on the assumption, that the same mutex is used. If nothing else, you can't prevent someone from forking your module and someone else to end up with both the original in the fork in the build. And if your case would break, that would break as well. [1] Some may argue that this is not "the same package", as different major versions can be considered different modules and because Semantic Import Versioning is intentionally part of the module design. However, I think in the context of the question, that's still reasonably "the same package". On Sun, 11 May 2025 at 06:45, Jason E. Aten <j.e.a...@gmail.com> wrote: > Is there a way to insure I've only got one version > of a package in a build? I need to make sure > a single mutex is used by all goroutines. > > Detailed back story is here: > https://github.com/golang/go/issues/73665 > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion visit > https://groups.google.com/d/msgid/golang-nuts/bdc40509-6b71-469e-82ce-c5fb4a64211bn%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/bdc40509-6b71-469e-82ce-c5fb4a64211bn%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/CAEkBMfHAjwz%2BcNsiP-5cGbM1NVxMc0Muazzj2dxqXH4McJwYHg%40mail.gmail.com.