title: pass recovery to upper goroutine golang
body: <p>I created an example where I  run function concurrently inside which I panic and recover:</p>
  <pre><code>package main
  
  import &quot;fmt&quot;
  
  func main() {
      // &quot;main&quot; recovery
      defer func() {
          if r := recover(); r != nil {
              fmt.Println(&quot;main goroutine paniced:&quot;, r)
          }
      }()
  
      // running function concurrently inside which I panic
      chanStr := make(chan string)
      go func() {
          // this &quot;internal&quot; goroutin recovery
          defer func() {
              if r := recover(); r != nil {
                  fmt.Println(&quot;internal goroutine paniced:&quot;, r)
              }
              chanStr &lt;- &quot;hello world&quot;
          }()
          // panicking and wanting recovery not only in &quot;internal&quot; recovery but in &quot;main&quot; recovery as well
          panic(&quot;NOT main goroutine&quot;)
      }()
      // waiting for chan with &quot;internal&quot; goroutine panicking and recovery
      str := &lt;-chanStr
      fmt.Println(str)
  
      // panic(&quot;main&quot;)
  }
  </code></pre>
  <p>It gives output:</p>
  <pre><code>internal goroutine panicked: NOT main goroutine
  hello world
  </code></pre>
  <p>Is it possible to change my code to make pass recovery from &quot;internal&quot; to &quot;main&quot;? In other words I want it to write down to console:</p>
  <pre><code>internal goroutine paniced: NOT main goroutine
  main goroutine paniced: main
  hello world
  </code></pre>
  <p>I tried to implement this by removing &quot;internal&quot; recovery func at all, but &quot;main&quot; recovery do not recover panic inside &quot;internal&quot; goroutine in this case.</p>
  <p><a href="https://play.golang.org/p/MXKSUZVzRr" rel="nofollow noreferrer">Playground</a></p>
  <h1>Update</h1>
  <p>I tried to follow @Momer's advice and  send an error through the channel and handle it in the main goroutine, instead of trying to bubble the panic up:</p>
  <pre><code>package main
  
  import (
      &quot;errors&quot;
      &quot;fmt&quot;
  )
  
  func main() {
      // &quot;main&quot; recovery
      defer func() {
          if r := recover(); r != nil {
              fmt.Println(&quot;main goroutine paniced:&quot;, r)
          }
      }()
  
      // running func concarantly inside which I panic
      chanStr := make(chan string)
      chanErr := make(chan error)
      var err error
      go func() {
          // this &quot;internal&quot; goroutin recovery
          defer func() {
              if r := recover(); r != nil {
                  fmt.Println(&quot;internal goroutine paniced:&quot;, r)
                  switch t := r.(type) {
                  case string:
                      fmt.Println(&quot;err is string&quot;)
                      err = errors.New(t)
                  case error:
                      fmt.Println(&quot;err is error&quot;)
                      err = t
                  default:
                      fmt.Println(&quot;err is unknown&quot;)
                      err = errors.New(&quot;Unknown error&quot;)
                  }
  
                  chanErr &lt;- err
                  chanStr &lt;- &quot;&quot;
              }
          }()
          // panicing and wanting recovery not only in &quot;internal&quot; recovery but in &quot;main&quot; recovery as well
          panic(&quot;NOT main goroutine&quot;)
          chanStr &lt;- &quot;hello world&quot;
          chanErr &lt;- nil
  
      }()
      // waiting for chan with &quot;internal&quot; goroutin panicing and recovery
      str := &lt;-chanStr
      err = &lt;-chanErr
      fmt.Println(str)
      fmt.Println(err)
  
      // panic(&quot;main&quot;)
  }
  </code></pre>
  <p>It gives error</p>
  <pre><code>all goroutines are asleep - deadlock
  </code></pre>
  <p>Full output:</p>
  <pre><code>go run /goPath/parentRecoverty2.go
  internal goroutine paniced: NOT main goroutine
  err is string
  fatal error: all goroutines are asleep - deadlock!
  
  goroutine 1 [chan receive]:
  main.main()
      /goPath/parentRecoverty2.go:48 +0x1d4
  
  goroutine 5 [chan send]:
  main.func·002()
      /goPath/parentRecoverty2.go:37 +0x407
  main.func·003()
      /goPath/parentRecoverty2.go:42 +0x130
  created by main.main
      /goPath/parentRecoverty2.go:46 +0x190
  exit status 2
  </code></pre>
  <p><a href="https://play.golang.org/p/ZlLd79UIge" rel="nofollow noreferrer">Update playground</a></p>