Make TTransportException unwrappable on Go 1.13+

Client: go

Go 1.13 introduced a new, optional, hidden interface for error
implementations to make them unwrappable [1]. We currently already kind
of support that (via TTransportException.Err), so just add a new
function to make it Go 1.13+ compatible.

[1] https://pkg.go.dev/errors@go1.13?tab=doc#pkg-overview
diff --git a/lib/go/thrift/transport_exception.go b/lib/go/thrift/transport_exception.go
index 9505b44..d2283ea 100644
--- a/lib/go/thrift/transport_exception.go
+++ b/lib/go/thrift/transport_exception.go
@@ -60,6 +60,10 @@
 	return p.err
 }
 
+func (p *tTransportException) Unwrap() error {
+	return p.err
+}
+
 func NewTTransportException(t int, e string) TTransportException {
 	return &tTransportException{typeId: t, err: errors.New(e)}
 }
diff --git a/lib/go/thrift/transport_exception_test.go b/lib/go/thrift/transport_exception_test.go
index b44314f..cf26258 100644
--- a/lib/go/thrift/transport_exception_test.go
+++ b/lib/go/thrift/transport_exception_test.go
@@ -36,25 +36,45 @@
 	return fmt.Sprintf("Timeout: %v", t.timedout)
 }
 
+type unwrapper interface {
+	Unwrap() error
+}
+
 func TestTExceptionTimeout(t *testing.T) {
 	timeout := &timeout{true}
 	exception := NewTTransportExceptionFromError(timeout)
 	if timeout.Error() != exception.Error() {
-		t.Fatalf("Error did not match: expected %q, got %q", timeout.Error(), exception.Error())
+		t.Errorf("Error did not match: expected %q, got %q", timeout.Error(), exception.Error())
 	}
 
 	if exception.TypeId() != TIMED_OUT {
-		t.Fatalf("TypeId was not TIMED_OUT: expected %v, got %v", TIMED_OUT, exception.TypeId())
+		t.Errorf("TypeId was not TIMED_OUT: expected %v, got %v", TIMED_OUT, exception.TypeId())
+	}
+
+	// NOTE: this can also be replaced by errors.Unwrap, but that requires
+	// go 1.13+.
+	if e, ok := exception.(unwrapper); !ok {
+		t.Error("Expected exception to be unwrappable, it is not.")
+	} else if e.Unwrap() != timeout {
+		t.Errorf("Unwrapped exception did not match: expected %v, got %v", timeout, e.Unwrap())
 	}
 }
 
 func TestTExceptionEOF(t *testing.T) {
 	exception := NewTTransportExceptionFromError(io.EOF)
 	if io.EOF.Error() != exception.Error() {
-		t.Fatalf("Error did not match: expected %q, got %q", io.EOF.Error(), exception.Error())
+		t.Errorf("Error did not match: expected %q, got %q", io.EOF.Error(), exception.Error())
 	}
 
 	if exception.TypeId() != END_OF_FILE {
-		t.Fatalf("TypeId was not END_OF_FILE: expected %v, got %v", END_OF_FILE, exception.TypeId())
+		t.Errorf("TypeId was not END_OF_FILE: expected %v, got %v", END_OF_FILE, exception.TypeId())
+	}
+
+	// NOTE: this can also be replaced by errors.Unwrap, but that requires
+	// go 1.13+.
+	if e, ok := exception.(unwrapper); !ok {
+		t.Error("Expected exception to be unwrappable, it is not.")
+	} else if e.Unwrap() != io.EOF {
+		t.Errorf("Unwrapped exception did not match: expected %v, got %v", io.EOF, e.Unwrap())
 	}
 }