4 ms·
I just can't stand taking three lines to unpack a value from a map or to return if error. Why can't I just say `return if err := somefunc(); err != nil` It's
by reedjosh 4y ago
I just can't stand taking three lines to unpack a value from a map or to return if error.
Why can't I just say `return if err := somefunc(); err != nil`
It's mega frustrating on top of the lack of generics and other abstractions.
And now that generics are coming about, I'm sure it will take forever until my current project can use them. My current project is in the k8s ecosystem which due to the lack of generics, implemented its own clever but awful type system.
- preseinger 4y agoThe problem here is that you think "error handling" is somehow different, and probably less important, than normal logic in your codebase. But Go asserts that the "sad path" is just as important as the "happy path".
- throwaway894345 4y agoI can't relate. Newline characters have never been burdensome to me, and they aid in visual structure (the control flow is represented by the visual structure of the program, not only for "good data" paths, but also for error paths). My programming problems are usually not related to localized keystroke boilerplate, but rather larger issues of abstraction and data modeling. > My current project is in the k8s ecosystem which due to the lack of generics, implemented its own clever but awful type system. The k8s ecosystem's type system is unrelated to generics. It has a concept of user-defined resource types, which means that users can provide an OpenAPI document describing their resource type which Kubernetes will then use to validate new user-provided resources of a given type. From the perspective of the Go compiler, these types are dynamic types--they can't be known at compile time. They aren't a candidate for generics in the host language. That said, it's often tedious to write a controller for these resource types, but that's because Kubernetes' controller frameworks are really complicated. They remind me of enterprise Java code with gratuitous abstraction. Maybe that abstraction serves some purpose, but it wasn't helping me and I ended up rewriting much of it in more standard Go (I didn't release it because it was prototype code and I didn't want to support it) and it was quite a lot simpler. I don't recall seeing many places where I felt that generics would be a significant improvement, but it's been a while.
- reedjosh 4y agoWell, if you don't know the structure of a resource ahead of time but know that it has a status.ready, I would think that would be a candidate for a generic? I haven't explored that much yet, but in retrospect I might even be able to convert all objects to a struct that has only status.ready without generics. I've only been in the ecosystem 6 months, but yeah larger abstractions are difficult too. I'm not a fan of the lack of sub-classing. I like writing a base class and concrete one, and it's quite difficult in Go unless you want to make everything an interface.
- assbuttbuttass 4y agoGo's equivalent of sub-classing is embedding
- reedjosh 4y agoYeah, and I kind of did that. But I've found it annoying and not great. For example in the base struct I had an interface and a ton of methods that use it. Then when I declared the concrete struct, I have to manually point the concrete type that matches that interface to the base class's interface. Composition doesn't really allow the same thing as inheritance. Composition typically means you'll have a motor and wheel struct in your car struct and maybe your car struct uses both in some drive method. Inheritance is more like having a car struct with a rev engine method, but no concrete engine set. So you can later make a Kia, set the motor to a type, and then call the base struct's rev engine method. Again, it's not impossible, just really ugly.
- throwaway894345 4y agoSeems pretty straightforward to me: type Car struct { Motor Motor Wheels [4]Wheel } type Motor interface { Rev() } type KiaMotor struct { ... } func (kia *KiaMotor) Rev() {} func NewKiaCar() Car { return Car{Motor: &KiaMotor{ ... }} }