Comments (9)
It wont be default because
- it is a very rare case, the fact that you;re first asking since liner implemented 1.5 years ago
- will loosen linter's current behavior that is expected by everyone else
I will think about making the option to opt-out from pivate fields being mandatory
from go-exhaustruct.
Then mark them as optional with field tags?
from go-exhaustruct.
@xobotyi Sure. What I am asking here is that default would be for lowercase fields to be optional by default.
from go-exhaustruct.
I will think about making the option to opt-out from pivate fields being mandatory
That. I do not want to change it for others. But having this option in golangci-lint would be awesome.
from go-exhaustruct.
Agree with @xobotyi. I'm not convinced private fields are inherently less important for callers witin the same package. What if you have a private field that needs to always be initialized within the package, e.g. a field that must be set inside a constructor? The analyzer offers no exhaustruct:"required"
comment to override your default setting now.
Overall the value add seems small, and enabling this behavior is likely to make enforcement more inflexible / more complex to configure.
from go-exhaustruct.
What if you have a private field that needs to always be initialized within the package, e.g. a field that must be set inside a constructor?
Then you create a New*
function as a constructor for that type.
from go-exhaustruct.
@mitar If you require the New
function you can't use the struct literal anyway. But if e.g. you have multiple constructors and always want the field to be set, now your choice of skipping enforcement bites you when you add a new private field and forget to initialize it in all constructors.
The key point is that there's nothing generally special about unexported fields that would suggest they shouldn't be set. Do you have some pattern in mind to motivate this special treatment?
from go-exhaustruct.
(I do not want to go in circles here, so feel free to stop if you feel we are doing that.)
To me the motivation is really simple. I have a package with exported struct. That struct has exported (uppercase) fields. Main use case for that package and the struct is external use. This is why there are exported fields. And there is no need to initialize anything, so there is no New*
function exported.
So external users of my package can use this struct and use it only be specifying exported fields. It works for them and the package and the struct is designed that it works only with exported fields set.
Private fields are just for caching/optimization/locks and are populated internally by methods of the struct as needed. I mean, sync.Mutex
is designed that zero value just works, for example.
Now I run this linter on the code of this package. And linter complains because there struct initialization code which uses the struct in the same way as external user would. And I would like that the linter simulates how the external user sees the struct. If I add a public field that it requires from me that I add it to all test cases for example. And if I add a private field, I in fact want that I do not add it all around the package - because I want to make sure things work without that private field being initialized, because this is the contact I have in my package for external users of the package.
Do you have some pattern in mind to motivate this special treatment?
I think the pattern is that if the struct is designed that it is directly usable (without New*
) for external users, then it can be used as such also internally. The fact that I export such struct is a contract/API I have for that struct. That setting only public fields is enough.
If I change the struct so that there is now a private field which has to be set, and add a New*
function to initialize, I am changing the contract and breaking API anyway.
But you are right, it probably makes no sense that this is a package-level/linter-level setting. Probably what I am really asking for is that this should be a struct-level setting. So instead of me having to add a struct tag to all private fields, that I could mark the whole struct as having private fields optional. Maybe through some comment or something.
from go-exhaustruct.
And if I add a private field, I in fact want that I do not add it all around the package - because I want to make sure things work without that private field being initialized, because this is the contact I have in my package for external users of the package.
That's a good point. I don't personally use many "plain-old data types" that have internal caching; those with complex state typically get constructors to enforce valid assignments, since I see the opposite case of initialization & validation requirements more often: in particular, maps and channels need to be assigned to avoid panics on writes. But the Go ecosystem probably differs from what I've written, given that the standard library usually accepts zero valued structs.
It does seem like more of a struct or package-level config, or perhaps even a global one if a required
directive existed.
from go-exhaustruct.
Related Issues (17)
- fix flag doesn't work HOT 1
- exhaustruct doesn't detect properties not defined in slice expressions HOT 1
- Support allowlisting via a comment rather than global config HOT 2
- Generic struct is ignored
- Adding regexp expressions slows the linter by 2 secs or more HOT 2
- Allow specifying optional field types using configuration HOT 1
- type definition in function scope not supported HOT 2
- Anonymous structs should not be checked for exhaustiveness HOT 4
- Multiply-nested named types for structs will not be subject to enforcement HOT 7
- The exclude rules support files? HOT 3
- Support allowlisting via struct literal level comment rather than global config
- Setting include/exclude package of code not package of struct HOT 1
- panics on local types with different amount of fields
- Add support for sruct composition HOT 2
- Setting to allow zero-values for structs HOT 14
- Consider downgrade to go 1.20 for golangci-lint compatibility HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from go-exhaustruct.