New syntax for import scopes.

179 views
Skip to first unread message

Denis Cheremisov

unread,
Apr 25, 2026, 8:15:18 AM (7 days ago)  Apr 25
to golang-nuts
Hi everyone, I'd like to discuss a common UX issue with large library ecosystems
(like gRPC, OTEL, or AWS SDK) where sub-packages often use overly generic names,
assuming they are the "center of the universe."

The Problem:
When using multiple sub-packages, we often get:

- manual.Resolver (from grpc/resolver/manual)
- jwt.Credentials (from grpc/credentials/jwt)

This leads to name collisions with other jwt or manual packages, forcing developers to
invent local aliases manually. Also, raw imports increases cognitive load during code reviews.

Proposed Solution:
Introduce a grouped import syntax that allows nesting sub-packages under a "parent" namespace:

    import grpc " google.golang.org/grpc " (
        .                // Embeds top-level grpc into the 'grpc' prefix
        jwt "credentials/jwt"
        manual "resolver/manual"
    )

Usage:
- grpc.ClientStream (from top-level)
- grpc.jwt.NewTokenFileCallCredentials()
- grpc.manual.Resolver

Key benefits :
- Scope isolation: No more collisions between grpc/jwt and other/jwt.
- Discoverability: IDEs can provide better autocompletion by grouping related sub-packages.
- Readability: The code clearly shows the origin of the sub-module without long, custom-prefixed  aliases like grpcjwt.
- This is a path grouping mechanism, not necessarily tied to Go modules, making it
 flexible for  both monorepos and fragmented ecosystems like OpenTelemetry.

What do you think about adding this to the Go grammar?

Mike Schinkel

unread,
Apr 26, 2026, 8:15:04 PM (5 days ago)  Apr 26
to Denis Cheremisov, golang-nuts
a common UX issue … where … packages often use overly generic names, 

assuming they are the "center of the universe."

I concur that this is a hugely annoying problem that requires aliasing.

What’s worse (in my experience) is developers on a team are never consistent with aliases across different files in a project. Lots of such aliases across a project make it is very hard to know whether the selector operand is a receiver value or a package qualifier, and code readability is supposed to be a primary virtue of Go. The upshot is conflicting-named aliases across .go files makes code maintenance a lot harder than it needs to be.

My “solution” has been to advocate that packages be named so they are unlikely to conflict with other package names, but admittedly my solution is grossly ineffective across the broad universe of Go packages.

Proposed Solution —  Introduce a grouped import syntax 

In your example, the prefix “grpc.” can mostly be derived directly from " google.golang.org/grpc/jwt ” so would not require a grouped import syntax. 

However, while I can see this being helpful in a single .go file, it does not resolve the issue of different prefixes used across different .go files. 

Also, based on Go developer community pushback I have seen on other feature requests that add concepts to the language, I cannot imagine support for the increased complexity of allowing `x.y.z` for package resolution vs. today’s current support of only `y.z`. I could be wrong about this, but if I am I would be very surprised.

ALTERNATE?: Aliases in go.mod

Rather than grouped imports, I would much rather see aliases tied to modules.  This would allow for common import names across a module, which addresses collisions, supports path grouping via naming conventions, and improves discoverability though would result in longer aliases (a reasonable tradeoff?), and it would mostly address the cross-file issue of different aliases that I have frequently experienced in the wild:
module github.com/example/example 


go 1.26.2

require(
// Aliases for sub-packages
google.golang.org/grpc v0.11.6 (
alias jwt grpcjwt
alias manual grpcman
)
// Alias added to end of require statement
github.com/mzattahri/cli v0.11.0 climux
)

// These package names squat on great var names
// Alias to use var names: `url`, `time`, and `bytes`
alias (
net/url neturl
time timepkg
bytes bytespkg
)
I also used this opportunity to suggest a common alias within a module for the standard library packages whose names squat on names developers frequently reach for variables they need to use with each respective package.

Thoughts all?

-Mike 


--
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...@googlegroups.com .
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/b999f866-0219-423a-af9d-495a4581f2fan%40googlegroups.com .

Jan Mercl

unread,
Apr 27, 2026, 3:35:07 AM (5 days ago)  Apr 27
to Denis Cheremisov, golang-nuts
On Sat, Apr 25, 2026 at 2:15 PM Denis Cheremisov
< denis.ch...@gmail.com > wrote:

> What do you think about adding this to the Go grammar?

First, a minor technical note: in Go, packages do not form a
hierarchy. The directory structure is a tree, but to the compiler, foo
and foo/bar are completely independent packages. The term
"sub-package" implies an object-oriented relationship that Go's design
avoids.

Regarding namespace collisions: you noted that developers are forced
to manually invent local aliases. While this does require a one-time
explicit declaration per file, this is already the canonical, solved
answer to the problem. Go favors flat namespaces and explicit,
localized renaming over language-level hierarchical namespaces
(grpc.jwt.Foo). The time spent writing an import alias is microscopic
compared to the overall time spent building and maintaining a package;
it is typically a "write once and forget" action.

Furthermore, the cost of implementing this is high. Introducing a new
grouped import syntax would require changes to go/ast and go/parser,
effectively breaking gofmt, goimports, gopls, and virtually every
third-party static analysis tool written over the last 15+ years.

Given that a working solution already exists via named imports,
breaking the entire ecosystem's tooling to bypass a few seconds of
one-time import aliasing seems like optimizing in the wrong place. The
massive disruption IMO simply doesn't justify the minor convenience.

-j

Stephen Illingworth

unread,
Apr 27, 2026, 4:01:45 AM (5 days ago)  Apr 27
to golang-nuts
On Monday, 27 April 2026 at 08:35:07 UTC+1 Jan Mercl wrote:
Regarding namespace collisions: you noted that developers are forced
to manually invent local aliases. While this does require a one-time
explicit declaration per file, this is already the canonical, solved
answer to the problem. Go favors flat namespaces and explicit,
localized renaming over language-level hierarchical namespaces
(grpc.jwt.Foo). The time spent writing an import alias is microscopic
compared to the overall time spent building and maintaining a package;
it is typically a "write once and forget" action. 

I don't suffer with this issue personally but I can see how local aliases might
benefit from being the same across all packages. But I agree that the solution
isn't to change the language itself. I think the better solution would be to write
an analyzer/linter that can be run on demand.




Reply all
Reply to author
Forward
0 new messages