Live data from Hacker News

Reusable and type-safe options for Go APIs

derekchiang.com

11–20 of 36 posts

Re: Reusable and type-safe options for Go APIs

#12
post #10

Earlier quoted context omitted.

The zero value problem would be a non-issue if Go had a built-in ?T type ("option T").

That's problematic, thanks to golang choosing to have always-nullable reference types. "option T*" would therefore be a tristate type, unless it was somehow specialised into representing nullability (obviously a major breaking change).

If mostly everyone uses Option instead of `nil`, the problem approaches a vanishing point. Not perfect, but still a massive improvement. Of course, generics won't be added until Go 2 anyway, at which point the community is free to make a breaking change, though I doubt they'll ditch `nil`.

Re: Reusable and type-safe options for Go APIs

#13
post #2

I've been using Go as my preferred language for almost a decade now. Hackish "clever" solutions like these coming from designers of the language like Rob Pike and Dace Cheney simply indicate that the language is hitting its limits of expressivity and needs to start thinking hard about overloading which is the right solution to problems like this.

I had the same feeling, and then i tried to implement the same solution in swift (which has more evolved constructs for enums and option sets), but it's actually not easy to do as well, if you want to handle all those constraints at the same time:

1/ a potentially big number of options, without creating functions with a huge list of parameters

2/ options with associated values (revision: int)

3/ reusable options between different operations, with type safety preventing wrong combination.

=> 1/ prevents you from using function overloading and default parameters

=> 2/ prevents you from using optionset (they're just bit masks)

and

=> 3/ prevents you from using regular sets or arrays as operation parameter.

I haven't spent more than half an hour trying to find a solution, so maybe there's a smart trick that would work, but it won't be an obvious solution either.

Re: Reusable and type-safe options for Go APIs

#14
I find I don't care for implementing the Options paradigm. More often then not, the things I've implemented have required parameters, and sometimes many of them. Mixing required and options often feels kludgy. I feel the Options method requires lots of documentation referencing, as opposed to more discoverable (via your editor) constructors. I tend to use explicit parameters or a struct with validators where every field is expected to be explicitly set.

This is not to say that using Options is wrong. Some things are highly customizable and having too many constructors would not be an appropriate solution. Worse would be a struct based config where you only set some fields some times. I just don't find myself creating these kinds of constructs. My most configurable things are usually server instances.

For those who do use the Options paradigm and find it useful, what are you creating?

Re: Reusable and type-safe options for Go APIs

#15
post #2

I've been using Go as my preferred language for almost a decade now. Hackish "clever" solutions like these coming from designers of the language like Rob Pike and Dace Cheney simply indicate that the language is hitting its limits of expressivity and needs to start thinking hard about overloading which is the right solution to problems like this.

Publicly released in an unstable state November 2009, meaning (almost) 8 years ago. Which is right where I personally draw the line for "almost a decade". It's been your preferred language from the moment it was available as a preview, three years before it hit 1.0?

That's right. I've been using Go since pre 1.0 times. I'm however not by and large a programmer by profession.

Re: Reusable and type-safe options for Go APIs

#16

I find I don't care for implementing the Options paradigm. More often then not, the things I've implemented have required parameters, and sometimes many of them. Mixing required and options often feels kludgy. I feel the Options method requires lots of documentation referencing, as opposed to more discoverable (via your editor) constructors. I tend to use explicit parameters or a struct with validators where every fi…

I have to say I agree. I came to Go from functional languages (primarily Lisp), so you'd think that the "Functional Options for Friendly APIs" pattern would appeal to me, but I've never seem an implementation that I've actually liked to use.

Re: Reusable and type-safe options for Go APIs

#18

How is it not cleaner and simpler to just use something of a builder pattern? srv = NewServer(addr).WithTLS(crt,key).WithRateLimit(30).WithPool(10).Start() if srv.Err() { // Handle }

In Go, chaining is not idiomatic. For one, it becomes more challenging to determine where the error occurred if you want to try to handle the error instead of failing. Also, it requires each function in the chain to detect if an error has already occurred.

Interfaces are generally a better solution.

Re: Reusable and type-safe options for Go APIs

#19
post #5
post #2

I've been using Go as my preferred language for almost a decade now. Hackish "clever" solutions like these coming from designers of the language like Rob Pike and Dace Cheney simply indicate that the language is hitting its limits of expressivity and needs to start thinking hard about overloading which is the right solution to problems like this.

Rob Pike and Dave Cheney know way better than me, but I can't help to think they're trying to be "easy rather than simple", here. Rob doesn't explain why a config struct is not good for him in his reference article, and Dave is saying that's because 1/ it needs to be passed even when it's empty and 2/ its zero values may be a trouble, giving the example of explicitly setting `Port` to 0 to let OS selecting first free…

For the zero value problem, a pointer is usually used rather than an "identifier value" like -1.

var price *float64

if price == nil {

  // Handle empty value

}

Re: Reusable and type-safe options for Go APIs

#20

I find I don't care for implementing the Options paradigm. More often then not, the things I've implemented have required parameters, and sometimes many of them. Mixing required and options often feels kludgy. I feel the Options method requires lots of documentation referencing, as opposed to more discoverable (via your editor) constructors. I tend to use explicit parameters or a struct with validators where every fi…

> More often then not, the things I've implemented have required parameters, and sometimes many of them.

The disconnect for OP here is that generalized systemic approach (think e.g. Java Beans for one of the earliest attempts) is necessary for the container-component architectures [but arguably un-necessary for application specific approaches (which has informed your experience.)]

Go, imho, is a poor fit for the container-component paradigm. It certainly can meet the initial requirements (context + options) but the lack of first class metadata facilities will limit the possibilities (sans code generation) in that architectural space.

[pre-emptive p.s.: "container" here /does not/ mean process level composition ala Docker, etc.]

Post reply on HN