4 ms·
The missing 'keyword arguments' could have been replaced with a struct passed to a function, no? Unless I'm missing something from Python, in Go you could repla
by Insanity 7y ago
The missing 'keyword arguments' could have been replaced with a struct passed to a function, no? Unless I'm missing something from Python, in Go you could replace this type of function:
func f(x int, y int, c string)
with something like this:
type funcOptions struct {
x, y int
c string
}
func f(o funcOptions) {}
f(funcOptions{x:3, y:-1, c: "hello"})
So the readability hit would have been more 'minimal.
- rauhl 7y agoThe problem there is that you then have a struct populating the namespace, which means it’s an entity to track, something to think about, something which populates autocomplete buffers. That’s not necessarily terrible, but it does impose complexity that simple keyword arguments do not.
- room271 7y agoYes, though you also have to consider default values as a possible source of error.
- Insanity 7y agoTrue, but you could provide default values as well if you use something like this: https://medium.com/@meeusdylan/go-reduce-function-parameters-19b785a87a59 https://medium.com/@meeusdylan/go-reduce-function-parameters... You'd need extra logic to know a value has not been set at all though. At which point the complexity might not outweigh simply..not using them.
- 013a 7y agoThis is very similar to the pattern the AWS SDK uses. In reality, its a small benefit to readability. You gain parameter names, which is very nice, but you end up with huge function call lines. describeTableOutput, err := dynamodbSvc.DescribeTableWithContext(ctx, &dynamodb.DescribeTableInput{ TableName: "users", }) With the main sources of pollution here being: 1) The forced inclusion of the package specifier on the type, rather than being able to directly reference the type via an import alias or something. You can alias the package name, but that's not a great general solution. 2) The forced inclusion of the type name at all. What, exactly, would be the type inference challenge if you were allowed to do something like this? describeTableOutput, err := dynamodbSvc.DescribeTableWithContext(ctx, &{ TableName: "users", }) I understand, if the parameter in the signature were an interface, this would not work. But its not; its a struct. It feels to me like this kind of inference should be allowed when a parameter is a struct, but maybe I'm missing some subtle corner case where it would not work. 3) All the context stuff; both as a function parameter, and the words "WithContext". I hate this. To be clear; Context is awesome. Every function which has the possibility of making network calls should accept a context. And that's the problem; modern Go libraries liter it everywhere, adding "WithContext" mirrors of existing functions to maintain backcompat. Context really should be "contextual"; omnipresent, overrideable, and only getting in the way when its needed. 95% of functions which interface with a context accept the context and pass the context; they're middlemen. They shouldn't have to even care about the context. Something like: func (d DynamoDB) DescribeTable(input *DescribeTableInput) (*DescribeTableOutput, error) { ctx := getContext() } func main() { setContext(context.Background()) describeTableOutput, err := dynamodbSvc.DescribeTable(&{ TableName: "users", }) } In other words, available via magic global functions. I'm sure there's some reason why this wouldn't work, or would have unintentional negative consequences, but I illustrate it only for the point that there are ways to accomplish this goal that are (probably) cleaner than making it a function parameter.
- Cthulhu_ 7y agoYeah, this is a known design pattern known as the Parameter Object (from Fowler's Refactoring book) (see https://wiki.c2.com/?ParameterObject https://wiki.c2.com/?ParameterObject). I am of two minds on it though, since it does add boilerplate to your codebase - especially if you start adding things like the builder pattern, or if you want to make arguments mandatory (e.g. via asserts). I use intellij which can offer inline parameter name hints, I think that's a good middle ground but it doesn't make things more readable outside of that editor.