5 ms·
> no default parameter values Hearing this leaves a bad taste in my mouth, because one of the (mis)features I've found in Go is its implicit default value in s
by yokohummer7 11y ago
> no default parameter values
Hearing this leaves a bad taste in my mouth, because one of the (mis)features I've found in Go is its implicit default value in struct initialization. In Go, you don't get a compile error when you miss some fields while initializing a struct. e.g.
type T struct {
a int
b string
c float64
}
t := T{c: 1.5}
will happily set `t.a` to 0 and `t.b` to an empty string. While this is useful for maintaining backward compatibility (adding more fields to a struct doesn't break upstream code), it also hinders discovering genuine mistakes at compile time. So typical Go programs end up using 0 or an empty string as a sentinel value. This is probably what made me feel Go's dynamic nature the most. It really is pretty close to a dynamic language.
- deleted 11y ago[deleted]
- fixermark 11y agoIt's one of those features that seems mad until and unless one runs into the situation that justifies it. Go provides default values to avoid the C error-factory of random undefined behavior resulting from re-use of whatever is in a memory address; that much is clear. But the reason Go lets you partially instantiate an object (and separates out construction from state) is to make it easier to write unit tests, where the common case is that you want to circumvent the "main line" object construction pathways.
- bradtgmurray 11y agoThat looks a lot like C to me, which I wouldn't call a dynamic language. typedef struct Foo { int a; int b; } Foo; Foo f = (Foo) { .a = 1 }; // This will initialize b to zero.
- hactually 11y agoIsn't it funny how C has so many ways to accomplish the same thing. Why did you use a typedef with a tag? typedef struct { int a; int b; } Foo; Foo f = { .a = 1 };
- to3m 11y agoTagless structs can't be forward-declared. (Obviously, this looks like a local struct, so there's possibly no need for forward declaration. But you might have a snippet to generate this sort of thing for you. Or maybe it's just force of habit. And so on.)
- masklinn 11y ago> Or maybe it's just force of habit. Or cargo-culting. edit: wow somebody felt threatened. I have no shame stating that I cargo-culted exactly that for a while before I actually wondered what I was doing.
- TillE 11y agoI'm guilty of this when writing C. I really have no desire to learn the language properly (it's hard enough to fit C++ in my brain), so I'll just follow the patterns others have set. Microsoft does stuff like: typedef struct _FOO { ... } FOO, *PFOO; Yeah ok fine, I'll do that.
- to3m 11y agoWhen doing this in your own libraries, be sure to document how to generate the struct tag name from the typedef name. (MS don't do this - but they're not consistent about it anyway.) Then when people see a typedef'd struct used somewhere in a header, they'll know how to forward declare it in their own headers.
- jerf 11y agoI should explicitly state I seem to be in the minority in the Go community here, but: You don't get a compiler error if you initialize by name. You do get a compiler error when you initialize by position. In my minority opinion, you can and should use that to your advantage whenever possible. Some structs are clearly "configuration-like", for instance, and you don't want an error if a new option shows up, which will probably default to whatever you had before anyhow. Some structs are clearly data structures, and you'd really like to know if your two-dimensional point suddenly grew a third parameter. Of course it's not a bright shining line, but it's often pretty easy to tell which you have, or which thing you want, and use the correct initialization. In this case, if you used: T{4, "hello", 3.5}} most future type changes to the T struct will become compiler errors. (It won't be if the types are compatible, for instance, changing the first to a float would still result in a legal struct. If you have richer types in play that is less of an issue.) golint will then complain at you, but you can pass a command-line switch to turn that off. (This, amusingly, puts me in the rare position of siding against the Go community, on the side of the language designers. Bet you may not have known there is such a position to take. :) )
- edsrzf 11y agoOne non-obvious downside is that the Go 1 compatibility guarantee doesn't apply to struct literals that don't use field names. (I suspect you're aware of this, but other readers might not be.) So it's possible that a future version of Go could add a field to some struct you're using and your code will stop compiling when you upgrade. It's an easy fix, of course, so it's not that big of a deal, but it's worth realizing.
- jerf 11y agoThe point is that if I'm using stuct literals, I want the compiler to stop me for those structs. I'm explicitly rejecting the idea that all struct changes should be possible without producing compiler errors. Compilers errors when the guarantees your code is based on changes is a feature, not a bug.
- copsarebastards 11y agoSo I get to go back and look at the struct to see the order every time I initialize an instance? Or watch everything break when the noob on the team alphabetizes the struct fields? Yeah, that's a great solution.
- andrewbinstock 11y agoI have long felt that floats should default to NaN, so that any attempt to perform operations with them before they're initialized results in an error.