4 ms·
As a very opinionated user of Go for ~6 years now... interface{} is almost always a code smell. I can judge a book by its cover with a grep and line count for
by leetrout 7y ago
As a very opinionated user of Go for ~6 years now...
interface{} is almost always a code smell. I can judge a book by its cover with a grep and line count for interface{} and reflect. If it's more than 20~30 for just about any small-medium size code base I dig deeper and look at why. Usually it is people being lazy and refusing to accept what is my twist on "idiomatic Go": a little bit of copying is better than a whole lot of abstraction[0]. Also devs telling me interface{} and type switches make it polymorphic are the ones who will always complain yet not leave the Go ecosystem. Hopefully generics in 2 solve this for everyone.
panic is great when you really want to crash. There are times to do this. I have only used it once in a batch job runner.
init() is a sin ESPECIALLY when you combine init() with the `.` (dot) imports. Pulling packages around for their magic side effects suck. Also the lack of some library maintainers to acknowledge init() can be poisonous... [1]
[0] https://go-proverbs.github.io/ https://go-proverbs.github.io/
[1] https://github.com/lib/pq/pull/455 https://github.com/lib/pq/pull/455
- frou_dh 7y agoDid you mean init combined with import underscore?
- wsy 7y agoI agree with the assessment of interface{}. However, the proverb you cite does not exist. It is: "A little copying is better than a little dependency.", which does not apply here.
- parsimo2010 7y agoThat it why GP said it was their twist.
- ben_jones 7y agoTwo valid use cases I've found for interface{}: Handling large arbitrary JSON objects where I need to operate on their keys but don't need to work with their values by unmarshaling to map[string]interface{}. The alternative would likely be code generation of struct definitions with JSON bindings, which is likely preferable if you already have code generation in your project, but can be an overhead in smaller ones. It can also be used to create your own syntactic wrappers around API's which consume interface{} such as encoding/json and database/sql: Unmarshal(r *http.Response, dst interface{}) ([]byte, error) and BulkInsert(tableName string, columns []string, values [][]interface{}) (time.Duration, error)
- deleted 7y ago[deleted]
- cle 7y agoHandling JSON is the one place where I’ve used interface{} and not felt dirty. Sometimes you really do need to model “anything” or “whatever”, especially when passing around arbitrary data without making assumptions about its schema.
- RSZC 7y agoI use it for shutdown channels. It doesn't matter what you're putting in the channel if you're never putting anything in the channel
- zeeboo 7y agoUsing chan struct{} is more efficient, and guarantees there is nothing being put into the channel. That's why you see it used on the Context type's Done method, for example. https://golang.org/pkg/context/#Context https://golang.org/pkg/context/#Context
- stevelosh 7y ago> Handling large arbitrary JSON objects where I need to operate on their keys but don't need to work with their values by unmarshaling to map[string]interface{}. If you just need the keys, you should unmarshal to `map[string]json.RawMessage` to avoid the overhead of parsing the values into objects only to throw them away without ever using them.
- erik_seaberg 7y agoEven https://golang.org/pkg/sync/#Map https://golang.org/pkg/sync/#Map requires interface{}. Any code that confines itself to raw slices and maps is probably using the wrong data structures for the problem.