4 ms·
The problem I have here, is that by being an interface you’ve suddenly made the type nilable. This leads to nasty bugs and segfaults, especially where nil is th
by flakes 2y ago
The problem I have here, is that by being an interface you’ve suddenly made the type nilable. This leads to nasty bugs and segfaults, especially where nil is the default construct for all interfaces.
Ideally sum types would be concrete/non-nilable somehow.
- greenavocado 2y agoThe workaround is even more cancerous but you could wrap it in a struct: type NotificationWrapper struct { // This field holds the actual notification data Value interface{} } And use it like: func NewPushNotification(token, title, message string, expires time.Time) NotificationWrapper { return NotificationWrapper{ Value: PushNotification{ DeviceToken: token, Title: title, Message: message, ExpiresAt: expires, }, } } And destructure it with something like func ProcessNotification(notification NotificationWrapper) string { switch n := notification.Value.(type) { Roll it all up in a nice syntax with a preprocessor haha
- flakes 2y agoThat still has the same issues depending on the usage. The default construct here is `NotificationWrapper{nil}`. If you want to actually guard it, you also need to make the Value field private as that nil becomes part of your public api otherwise. type NotificationWrapper struct { // This field holds the actual notification data value interface{} } Within `ProcessNotification` you'd also want to always assert the struct is initialized. You have to handle that error case via `err` or `panic`. With a true sum type, you could be assured that the value is always concrete, removing the need for error handling, which otherwise complicates the business logic of your application. Errors that should be safeguarded against by the compiler become run time checks, eating up cycles on the CPU, or paniced upon, potentially leading to segfaults which can only be caught by tests (not asserted valid via the act of compiling).