On Thu, 29 Sep 2016 19:35:49 +0200 Axel Wagner <axel.wagner...@googlemail.com> wrote:
[...] > > 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...) > } Henrik tried to highlight a caveat of this approach: --------8<-------- package main type Logger struct { } func (l *Logger) Printf(args ...interface{}) { // Do nothing, intentionally to be OK with nils } func main() { var n int = 42 var wi interface{} = n l, _ := wi.(Logger) l.Printf("whatever") } --------8<-------- (Playground link: <https://play.golang.org/p/MpZFXvHb3i>). This program does not crash, it called a method on a Logger-typed value which was "automagically produced" from an integer by actively abusing the two-argument form of type assertion. It's abusing because if you want to call functions on your logger while not being interested whether it was set or not, you just don't need to do anything besides type-asserting its container value to be *Logger. That works because interface{} contains two things: the type and the value of that type. The latter can perfectly be nil for pointer types. To demonstrate: --------8<-------- package main import "fmt" type Logger struct { } func (l *Logger) Printf(args ...interface{}) { if l == nil { fmt.Println("I'm nil") } else { fmt.Println("I'm not nil") } } func main() { set := &Logger{} missing := (*Logger)(nil) var wi interface{} wi = set log(wi) wi = missing log(wi) } func log(wi interface{}) { l := wi.(*Logger) l.Printf() } --------8<-------- (Playground link: <https://play.golang.org/p/k908qwqad9>). As you can see here, we "blindly" type-assert the value to be *Logger in the log() function using it, and on the first call that "decapsulates" a non-nil pointer value while on the second call it fetches a nil value. The point is: in both cases these values have the type *Logger. Maybe you forgot about the distinction between a nil value of interface type and a nil value _contained_ in an interface value? I mean <https://golang.org/doc/faq#nil_error>. -- 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.