| // 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 | 
 | } |