|  | // 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. | 
|  |  | 
|  | // Issue 31419: race in getitab when two goroutines try | 
|  | // to do the same failed interface conversion. | 
|  |  | 
|  | package main | 
|  |  | 
|  | type T int | 
|  |  | 
|  | func (t T) M() {} | 
|  |  | 
|  | type I interface { | 
|  | M() | 
|  | M2() | 
|  | } | 
|  |  | 
|  | var t T | 
|  | var e interface{} = &t | 
|  | var ok = false | 
|  | var ch = make(chan int) | 
|  |  | 
|  | func main() { | 
|  | _, ok = e.(I) // populate itab cache with a false result | 
|  |  | 
|  | go f() // get itab in a loop | 
|  |  | 
|  | var i I | 
|  | for k := 0; k < 10000; k++ { | 
|  | i, ok = e.(I) // read the cached itab | 
|  | if ok { | 
|  | println("iteration", k, "i =", i, "&t =", &t) | 
|  | panic("conversion succeeded") | 
|  | } | 
|  | } | 
|  | <-ch | 
|  | } | 
|  |  | 
|  | func f() { | 
|  | for i := 0; i < 10000; i++ { | 
|  | f1() | 
|  | } | 
|  | ch <- 1 | 
|  | } | 
|  |  | 
|  | func f1() { | 
|  | defer func() { | 
|  | err := recover() | 
|  | if err == nil { | 
|  | panic("did not panic") | 
|  | } | 
|  | }() | 
|  | i := e.(I) // triggers itab.init, for getting the panic string | 
|  | _ = i | 
|  | } |