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.

Reply via email to