On Thu, Sep 29, 2016 at 7:09 PM, Konstantin Khomoutov < flatw...@users.sourceforge.net> wrote:
> I think you still can't "get" the chief distinction: it lies in typing > not in similarities of syntax. > > For > > m := make(map[string]interface{}) > > there's a well-defined zero value for the type of values this map holds. > > While somewhat dubious, this is useful for maps which merely record the > fact the particular set of keys is "known"; consider: > > m := make(map[string]bool) > m["three"] = true > > And now: > > * m["one"] evaluates to false > * m["two"] evaluates to false > * m["three"] evaluates to true > * m["four"] evaluates to false > ...and so on. > > With type assertions, I really fail to see how returning the zero value > for the target type in case the type assertion failed can be useful. > For example: You are using context.Context, save a thing under a given key and then provide functions to extract it and do stuff to it (say, you have a logger saved in a context). You also make, as a good go citizen, the zero value of the thing useful. You can still write that, like this: func Log(ctx context.Context, fmt string, v ...interface{}) { l, _ := ctx.Value(loggerKey).(*Logger) l.Printf(fmt, v...) } (so, there clearly is no type-problem here, otherwise this wouldn't work or make sense), if you assume that logging to a nil-*Logger would be a nop. If the one-argument form were equivalent, you could do func Log(ctx context.Context, fmt string, v ...interface{}) { ctx.Value(loggerKey).(*Logger).Printf(fmt, v...) } Similarly (and closer to your example): func WithDebug(ctx context.Context) context.Context { return context.WithValue(ctx, debugKey, true) } func DebugLog(ctx context.Context, fmt.String, v ...interface{}) { if ctx.Value(debugKey).(bool) { Debug(ctx, fmt, v...) } } Now, granted, the difference in those particular cases isn't huge, but there are similar cases to be constructed; basically, every time a) the zero value is a useful value (which it should be <http://go-proverbs.github.io/>) and b) you then want to use it in an expression, you now need to put it into a separate variable. I think the context-example is particularly illustrative, because you are supposed to not depend on a value being present in it and you don't have any other type-information. I'd argue, that it's a sign of idiomatic go code to use v, _ := ctx.Value(key).(someType); making the zero value a useful default and then use that default, if it isn't given otherwise. Claiming that it would be useless to just use a zero value on a failing type-assertion means contending the notion of zero values being useful things (see also <https://speakerdeck.com/campoy/understanding-nil>). Which is *exactly* the same notion that make the zero value a reasonable and good default to return from a map-access. (that is also the reason why I don't like the implication that a failed type-assertion is something to panic' about. It's based on the assumption that zero values are dangerous, broken or useless) -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.