| // run |
| |
| // Copyright 2019 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // short-circuiting interface-to-concrete comparisons |
| // will not miss panics |
| |
| package main |
| |
| import ( |
| "log" |
| "strings" |
| ) |
| |
| func main() { |
| var ( |
| x interface{} |
| p *int |
| s []int |
| l *interface{} |
| r []*int |
| ) |
| tests := []struct { |
| name string |
| errStr string |
| f func() |
| }{ |
| {"switch case", "", func() { |
| switch x { |
| case x.(*int): |
| } |
| }}, |
| {"interface conversion", "", func() { _ = x == x.(error) }}, |
| {"type assertion", "", func() { _ = x == x.(*int) }}, |
| {"out of bounds", "", func() { _ = x == s[1] }}, |
| {"nil pointer dereference #1", "", func() { _ = x == *p }}, |
| {"nil pointer dereference #2", "nil pointer dereference", func() { _ = *l == r[0] }}, |
| } |
| |
| for _, tc := range tests { |
| testFuncShouldPanic(tc.name, tc.errStr, tc.f) |
| } |
| } |
| |
| func testFuncShouldPanic(name, errStr string, f func()) { |
| defer func() { |
| e := recover() |
| if e == nil { |
| log.Fatalf("%s: comparison did not panic\n", name) |
| } |
| if errStr != "" { |
| if !strings.Contains(e.(error).Error(), errStr) { |
| log.Fatalf("%s: wrong panic message\n", name) |
| } |
| } |
| }() |
| f() |
| } |