3 ms·
Say you put a single type Foo in its own package to ensure that nothing ever — intentionally or unintentionally — touches its unexported (private) fields. If "
by frou_dh 7y ago
Say you put a single type Foo in its own package to ensure that nothing ever — intentionally or unintentionally — touches its unexported (private) fields.
If "Dot Imports" are frowned upon, it means that your other code using that type is always going to have to refer to it as the stuttering "foo.Foo" rather than "Foo". That's not great.
- zeveb 7y agoPutting a type into a type-specific package like that is considered (IMHO at least) unidiomatic in the first place, so this isn't a situation which can happen in practice.
- frou_dh 7y agoWhat's the counterargument to the expressed benefit?
- klodolph 7y agoIt breaks the ability to Ctrl-F to find uses of the package foo. It’s surprising to other Go programmers. If you’re working by yourself, go wild and do what you want. On teams, I’m much more likely to need to search through somebody else’s file to understand it or find something. It also means that additions to foo might conflict with definitions in your package. The reason this feature exists is to break circular dependencies in unit tests. So in foo_test, you might import ( . "foo" "fooutil" )
- frou_dh 7y agoThis makes sense but it's more like general advice for why typical packages should not be import-dotted. I was talking about a very specific kind of low-pollution package that will export essentially nothing bar a single type (maybe a NewFoo constructor too). The package isn't a bucket, it's a barrier. (I hope people move beyond ctrl-f/grepping, to tooling that has semantic understanding of definitions/references. Go go gopls & GoLand!)
- klodolph 7y agoIf you already have the answer, why are you asking the question? (You can’t find Foo just by looking at syntax at all, you would need to parse both the package where it is used and the package where it is defined. Using normal imports, you can get by with only parsing the call site.)
- sagichmal 7y ago> Say you put a single type Foo in its own package to ensure that nothing ever — intentionally or unintentionally — touches its unexported (private) fields. This is not a good reason to move a type to its own package. Packages are for grouping related functionality.
- erik_seaberg 7y agoPackages have to be used for access control as long as there’s no other way to do it. You’re committing to support uses of anything you make public.
- sagichmal 7y agoWhat? Exporting a type or field is an opt-in decision, you don't need a special package per type to do it. If the fear is that other types or functions in the same package can access the unexported fields, that's unavoidable, making a new package per type doesn't reduce the risk.
- LukeShu 7y agoDo that, then do a type alias in the package you would "like" for it to be imported from: mypkg/internal/foo/foo.go: type Foo struct { … } mypkg/mypkg.go: import "mypkg/internal/foo" type Foo = foo.Foo Then, it can be imported from "mypkg` and used as `mypkg.Foo`.
- frou_dh 7y agoNeat, you win at puzzle solving! I forget that the user-level type alias feature exists... maybe since it was introduced relatively late in the Go 1.x timeline.
- azth 7y agoThis is a symptom of another underlying issue with golang. It doesn't let you import structs or functions from other packages, you can only import the top level package name, and then have to refer to entries in the package by the package name. Compare to Java, Scala, Kotlin, etc. where you are able to import individual classes (and methods and functions in the case of the latter two).