THRIFT-5650: Implement UUID in Go compiler

Client: go
diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc
index 45d047a..90353ce 100644
--- a/compiler/cpp/src/thrift/generate/t_go_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc
@@ -97,6 +97,11 @@
       } else {
         return value->get_double() == 0.;
       }
+
+    case t_base_type::TYPE_UUID:
+      // it's hard to detect all zero uuid here, so just always inline it.
+      return false;
+
     default:
       throw "compiler error: unhandled type";
     }
@@ -150,7 +155,9 @@
     case t_base_type::TYPE_I32:
     case t_base_type::TYPE_I64:
     case t_base_type::TYPE_DOUBLE:
+    case t_base_type::TYPE_UUID:
       return !has_default;
+
     default:
       break;
     }
@@ -867,7 +874,7 @@
   t_type* type = tconst->get_type();
   string name = publicize(tconst->get_name());
   t_const_value* value = tconst->get_value();
-  if (type->is_base_type() || type->is_enum()) {
+  if (type->is_enum() || (type->is_base_type() && ((t_base_type*)type)->get_base() != t_base_type::TYPE_UUID)) {
     indent(f_consts_) << "const " << name << " = " << render_const_value(type, value, name) << endl;
   } else {
     f_const_values_ << indent() << name << " = " << render_const_value(type, value, name) << endl
@@ -884,8 +891,10 @@
  */
 string t_go_generator::render_const_value(t_type* type, t_const_value* value, const string& name, bool opt) {
   string typedef_opt_ptr;
+  string typedef_opt;
   if (type->is_typedef()) {
-    typedef_opt_ptr = type_name(type) + "Ptr";
+    typedef_opt = publicize(type_name(type));
+    typedef_opt_ptr = typedef_opt + "Ptr";
   }
   type = get_true_type(type);
   std::ostringstream out;
@@ -966,6 +975,19 @@
           out << '"' + get_escaped_string(value) + '"';
           break;
 
+        case t_base_type::TYPE_UUID:
+          if (typedef_opt_ptr != "") {
+            out << typedef_opt_ptr << "(" << typedef_opt;
+          } else {
+            out << "thrift.TuuidPtr";
+          }
+          out << "(";
+          out << "thrift.Must(thrift.ParseTuuid(\"" + get_escaped_string(value) + "\"))";
+          if (typedef_opt_ptr != "") {
+            out << ")";
+          }
+          break;
+
         default:
           throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
       }
@@ -1007,6 +1029,17 @@
 
           break;
 
+        case t_base_type::TYPE_UUID:
+          if (typedef_opt != "") {
+            out << typedef_opt << "(";
+          }
+          out << "thrift.Must(thrift.ParseTuuid(\"" + get_escaped_string(value) + "\"))";
+          if (typedef_opt != "") {
+            out << ")";
+          }
+
+          break;
+
         default:
           throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
       }
@@ -2425,6 +2458,15 @@
           f_remote << indent() << "}" << endl;
           break;
 
+        case t_base_type::TYPE_UUID:
+          f_remote << indent() << "argvalue" << i << ", " << err
+                   << " := (thrift.ParseTuuid(flag.Arg(" << flagArg << ")))" << endl;
+          f_remote << indent() << "if " << err << " != nil {" << endl;
+          f_remote << indent() << "  Usage()" << endl;
+          f_remote << indent() << "  return" << endl;
+          f_remote << indent() << "}" << endl;
+          break;
+
         default:
           throw("Invalid base type in generate_service_remote");
         }
@@ -2539,6 +2581,7 @@
         case t_base_type::TYPE_I32:
         case t_base_type::TYPE_I64:
         case t_base_type::TYPE_DOUBLE:
+        case t_base_type::TYPE_UUID:
           f_remote << "value" << i;
           break;
 
@@ -3052,6 +3095,10 @@
         out << "ReadDouble(ctx)";
         break;
 
+      case t_base_type::TYPE_UUID:
+        out << "ReadUUID(ctx)";
+        break;
+
       default:
         throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase);
       }
@@ -3301,6 +3348,10 @@
         out << "WriteDouble(ctx, float64(" << name << "))";
         break;
 
+      case t_base_type::TYPE_UUID:
+        out << "WriteUUID(ctx, thrift.Tuuid(" << name << "))";
+        break;
+
       default:
         throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase);
       }
@@ -3500,6 +3551,7 @@
       case t_base_type::TYPE_I32:
       case t_base_type::TYPE_I64:
       case t_base_type::TYPE_DOUBLE:
+      case t_base_type::TYPE_UUID:
         out << tgt << " != " << src;
         break;
 
@@ -3807,6 +3859,9 @@
     case t_base_type::TYPE_DOUBLE:
       return "thrift.DOUBLE";
 
+    case t_base_type::TYPE_UUID:
+      return "thrift.UUID";
+
     default:
       break;
     }
@@ -3897,6 +3952,9 @@
     case t_base_type::TYPE_DOUBLE:
       return maybe_pointer + "float64";
 
+    case t_base_type::TYPE_UUID:
+      return maybe_pointer + "thrift.Tuuid";
+
     default:
       break;
     }
diff --git a/compiler/cpp/src/thrift/generate/validator_parser.cc b/compiler/cpp/src/thrift/generate/validator_parser.cc
index 84261fe..a0aee46 100644
--- a/compiler/cpp/src/thrift/generate/validator_parser.cc
+++ b/compiler/cpp/src/thrift/generate/validator_parser.cc
@@ -48,6 +48,7 @@
 std::vector<validation_rule*> validation_parser::parse_field(
     t_type* type,
     std::map<std::string, std::vector<std::string>>& annotations) {
+  std::vector<validation_rule*> empty_rules;
   if (type->is_typedef()) {
     type = type->get_true_type();
   }
@@ -58,7 +59,7 @@
     switch (tbase) {
     case t_base_type::TYPE_UUID:
     case t_base_type::TYPE_VOID:
-      break;
+      return empty_rules;
     case t_base_type::TYPE_I8:
     case t_base_type::TYPE_I16:
     case t_base_type::TYPE_I32:
@@ -547,4 +548,4 @@
         + annotation_value;
   }
   return function;
-}
\ No newline at end of file
+}
diff --git a/lib/go/test/EqualsTest.thrift b/lib/go/test/EqualsTest.thrift
index 57ce131..1732f31 100644
--- a/lib/go/test/EqualsTest.thrift
+++ b/lib/go/test/EqualsTest.thrift
@@ -20,6 +20,7 @@
 typedef i8 mybyte
 typedef string mystr
 typedef binary mybin
+typedef uuid myuuid
 
 enum EnumFoo {
   e1
@@ -51,6 +52,10 @@
   22: optional mystr OptMyStrFoo,
   23: mybin MyBinFoo,
   24: optional mybin OptMyBinFoo,
+  25: uuid UUIDFoo,
+  26: optional uuid OptUUIDFoo,
+  27: myuuid MyUUIDFoo,
+  28: optional myuuid OptMyUUIDFoo,
 }
 
 struct StructEqualsFoo {
@@ -79,6 +84,10 @@
     18: optional list<mystr> OptMyStrListFoo,
     19: list<mybin> MyBinListFoo,
     20: optional list<mybin> OptMyBinListFoo,
+    21: list<uuid> UUIDListFoo,
+    22: optional list<uuid> OptUUIDListFoo,
+    23: list<myuuid> MyUUIDListFoo,
+    24: optional list<myuuid> OptMyUUIDListFoo,
 }
 
 struct SetEqualsFoo {
@@ -102,6 +111,10 @@
     18: optional set<mystr> OptMyStrSetFoo,
     19: set<mybin> MyBinSetFoo,
     20: optional set<mybin> OptMyBinSetFoo,
+    21: set<uuid> UUIDSetFoo,
+    22: optional set<uuid> OptUUIDSetFoo,
+    23: set<myuuid> MyUUIDSetFoo,
+    24: optional set<myuuid> OptMyUUIDSetFoo,
 }
 
 struct MapEqualsFoo {
@@ -125,4 +138,8 @@
     18: optional map<i64, mybyte> OptInt64MyByteMapFoo,
     19: map<mybyte, i64> MyByteInt64MapFoo,
     20: optional map<mybyte, i64> OptMyByteInt64MapFoo,
+    21: map<i64, uuid> UUIDMapFoo,
+    22: optional map<i64, uuid> OptUUIDMapFoo,
+    23: map<i64, myuuid> MyUUIDMapFoo,
+    24: optional map<i64, myuuid> OptMyUUIDMapFoo,
 }
diff --git a/lib/go/test/tests/equals_test.go b/lib/go/test/tests/equals_test.go
index 3bd14b6..b8adc77 100644
--- a/lib/go/test/tests/equals_test.go
+++ b/lib/go/test/tests/equals_test.go
@@ -23,9 +23,16 @@
 	"strconv"
 	"testing"
 
+	"github.com/apache/thrift/lib/go/thrift"
+
 	"github.com/apache/thrift/lib/go/test/gopath/src/equalstest"
 )
 
+var (
+	equalstestUUID1 = thrift.Must(thrift.ParseTuuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
+	equalstestUUID2 = thrift.Must(thrift.ParseTuuid("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
+)
+
 func TestEquals(t *testing.T) {
 	// test basic field
 	basicTgt, basicSrc := genBasicFoo(), genBasicFoo()
@@ -117,19 +124,19 @@
 func genBasicFoo() *equalstest.BasicEqualsFoo {
 	return &equalstest.BasicEqualsFoo{
 		BoolFoo:      true,
-		OptBoolFoo:   &(&struct{ x bool }{true}).x,
+		OptBoolFoo:   thrift.BoolPtr(true),
 		I8Foo:        1,
-		OptI8Foo:     &(&struct{ x int8 }{1}).x,
+		OptI8Foo:     thrift.Int8Ptr(1),
 		I16Foo:       2,
-		OptI16Foo:    &(&struct{ x int16 }{2}).x,
+		OptI16Foo:    thrift.Int16Ptr(2),
 		I32Foo:       3,
-		OptI32Foo:    &(&struct{ x int32 }{3}).x,
+		OptI32Foo:    thrift.Int32Ptr(3),
 		I64Foo:       4,
-		OptI64Foo:    &(&struct{ x int64 }{4}).x,
+		OptI64Foo:    thrift.Int64Ptr(4),
 		DoubleFoo:    5,
-		OptDoubleFoo: &(&struct{ x float64 }{5}).x,
+		OptDoubleFoo: thrift.Float64Ptr(6),
 		StrFoo:       "6",
-		OptStrFoo:    &(&struct{ x string }{"6"}).x,
+		OptStrFoo:    thrift.StringPtr("6"),
 		BinFoo:       []byte("7"),
 		OptBinFoo:    []byte("7"),
 		EnumFoo:      equalstest.EnumFoo_e1,
@@ -140,6 +147,10 @@
 		OptMyStrFoo:  equalstest.MystrPtr(equalstest.Mystr("9")),
 		MyBinFoo:     equalstest.Mybin("10"),
 		OptMyBinFoo:  equalstest.Mybin("10"),
+		UUIDFoo:      equalstestUUID1,
+		OptUUIDFoo:   thrift.TuuidPtr(equalstestUUID1),
+		MyUUIDFoo:    equalstest.Myuuid(equalstestUUID1),
+		OptMyUUIDFoo: equalstest.MyuuidPtr(equalstest.Myuuid(equalstestUUID1)),
 	}
 }
 
@@ -172,6 +183,10 @@
 		OptMyStrListFoo:        []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")},
 		MyBinListFoo:           []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")},
 		OptMyBinListFoo:        []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")},
+		UUIDListFoo:            []thrift.Tuuid{equalstestUUID1, equalstestUUID2},
+		OptUUIDListFoo:         []thrift.Tuuid{equalstestUUID1, equalstestUUID2},
+		MyUUIDListFoo:          []equalstest.Myuuid{equalstest.Myuuid(equalstestUUID1), equalstest.Myuuid(equalstestUUID2)},
+		OptMyUUIDListFoo:       []equalstest.Myuuid{equalstest.Myuuid(equalstestUUID1), equalstest.Myuuid(equalstestUUID2)},
 	}
 }
 
@@ -197,6 +212,10 @@
 		OptMyStrSetFoo:        []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")},
 		MyBinSetFoo:           []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")},
 		OptMyBinSetFoo:        []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")},
+		UUIDSetFoo:            []thrift.Tuuid{equalstestUUID1, equalstestUUID2},
+		OptUUIDSetFoo:         []thrift.Tuuid{equalstestUUID1, equalstestUUID2},
+		MyUUIDSetFoo:          []equalstest.Myuuid{equalstest.Myuuid(equalstestUUID1), equalstest.Myuuid(equalstestUUID2)},
+		OptMyUUIDSetFoo:       []equalstest.Myuuid{equalstest.Myuuid(equalstestUUID1), equalstest.Myuuid(equalstestUUID2)},
 	}
 }
 
@@ -227,6 +246,10 @@
 		OptInt64MyByteMapFoo:     map[int64]equalstest.Mybyte{6: equalstest.Mybyte(6), 5: equalstest.Mybyte(5), 4: equalstest.Mybyte(4), 3: equalstest.Mybyte(3), 2: equalstest.Mybyte(2), 1: equalstest.Mybyte(1)},
 		MyByteInt64MapFoo:        map[equalstest.Mybyte]int64{equalstest.Mybyte(6): 6, equalstest.Mybyte(5): 5, equalstest.Mybyte(4): 4, equalstest.Mybyte(3): 3, equalstest.Mybyte(2): 2, equalstest.Mybyte(1): 1},
 		OptMyByteInt64MapFoo:     map[equalstest.Mybyte]int64{equalstest.Mybyte(6): 6, equalstest.Mybyte(5): 5, equalstest.Mybyte(4): 4, equalstest.Mybyte(3): 3, equalstest.Mybyte(2): 2, equalstest.Mybyte(1): 1},
+		UUIDMapFoo:               map[int64]thrift.Tuuid{1: equalstestUUID1, 2: equalstestUUID2},
+		OptUUIDMapFoo:            map[int64]thrift.Tuuid{1: equalstestUUID1, 2: equalstestUUID2},
+		MyUUIDMapFoo:             map[int64]equalstest.Myuuid{1: equalstest.Myuuid(equalstestUUID1), 2: equalstest.Myuuid(equalstestUUID2)},
+		OptMyUUIDMapFoo:          map[int64]equalstest.Myuuid{1: equalstest.Myuuid(equalstestUUID1), 2: equalstest.Myuuid(equalstestUUID2)},
 	}
 }
 
diff --git a/lib/go/thrift/json_protocol.go b/lib/go/thrift/json_protocol.go
index 8b1bb52..6743a7f 100644
--- a/lib/go/thrift/json_protocol.go
+++ b/lib/go/thrift/json_protocol.go
@@ -524,6 +524,8 @@
 		return "set", nil
 	case LIST:
 		return "lst", nil
+	case UUID:
+		return "uid", nil
 	}
 
 	e := fmt.Errorf("Unknown fieldType: %d", int(fieldType))
@@ -554,6 +556,8 @@
 		return TType(SET), nil
 	case "lst":
 		return TType(LIST), nil
+	case "uid":
+		return TType(UUID), nil
 	}
 
 	e := fmt.Errorf("Unknown type identifier: %s", fieldType)
diff --git a/test/ConstantsDemo.thrift b/test/ConstantsDemo.thrift
index 2245657..8fac6db 100644
--- a/test/ConstantsDemo.thrift
+++ b/test/ConstantsDemo.thrift
@@ -20,11 +20,16 @@
 namespace cpp yozone
 namespace erl consts_
 namespace haxe constantsDemo
+namespace go constantsdemo
+
+typedef uuid myUUID
 
 struct thing {
   1: i32  hello,
   2: i32  goodbye
   3: uuid id
+  4: myUUID my_id
+  5: optional myUUID my_optional_id
 }
 
 enum enumconstants {
@@ -51,12 +56,15 @@
 const string GEN_STRING = "asldkjasfd"
 
 const double e10 = 1e10   // fails with 0.9.3 and earlier
-const double e11 = -1e10  
+const double e11 = -1e10
 
 // uuids are accepted with or without curly braces
 const uuid GEN_UUID =  '00000000-4444-CCCC-ffff-0123456789ab'
 const uuid GEN_GUID = '{00112233-4455-6677-8899-aaBBccDDeeFF}'
 
+const myUUID MY_UUID =  '00000000-4444-CCCC-ffff-0123456789ab'
+const myUUID MY_GUID = '{00112233-4455-6677-8899-aaBBccDDeeFF}'
+
 const map<i32,i32> GEN_MAP = { 35532 : 233, 43523 : 853 }
 const list<i32> GEN_LIST = [ 235235, 23598352, 3253523 ]
 
@@ -64,9 +72,9 @@
 
 const map<string,i32> GEN_MAP2 = { "hello" : 233, "lkj98d" : 853, 'lkjsdf' : 098325 }
 
-const thing GEN_THING = { 'hello' : 325, 'goodbye' : 325352, 'id' : '{00112233-4455-6677-8899-aaBBccDDeeFF}' }
+const thing GEN_THING = { 'hello' : 325, 'goodbye' : 325352, 'id' : '{00112233-4455-6677-8899-aaBBccDDeeFF}', 'my_id': '00000000-4444-CCCC-ffff-0123456789ab', 'my_optional_id': '00000000-4444-CCCC-ffff-0123456789ab' }
 
-const map<i32,thing> GEN_WHAT = { 35 : { 'hello' : 325, 'goodbye' : 325352, 'id' : '00000000-4444-CCCC-ffff-0123456789ab' } }
+const map<i32,thing> GEN_WHAT = { 35 : { 'hello' : 325, 'goodbye' : 325352, 'id' : '00000000-4444-CCCC-ffff-0123456789ab', 'my_id': '00000000-4444-CCCC-ffff-0123456789ab', 'my_optional_id': '00000000-4444-CCCC-ffff-0123456789ab' } }
 
 const set<i32> GEN_SET = [ 235, 235, 53235 ]
 
diff --git a/test/go/Makefile.am b/test/go/Makefile.am
index 32c2be0..abed923 100644
--- a/test/go/Makefile.am
+++ b/test/go/Makefile.am
@@ -26,7 +26,7 @@
 endif
 
 THRIFTCMD = $(THRIFT) -out src/gen --gen go:thrift_import=github.com/apache/thrift/lib/go/thrift,package_prefix=github.com/apache/thrift/test/go/src/gen/$(COMPILER_EXTRAFLAG)
-THRIFTTEST = $(top_srcdir)/test/v0.16/ThriftTest.thrift
+THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift
 
 precross: bin/testclient bin/testserver
 
@@ -40,6 +40,7 @@
 	mkdir -p src/gen
 	$(THRIFTCMD) ThriftTest.thrift
 	$(THRIFTCMD) ../StressTest.thrift
+	$(THRIFTCMD) ../ConstantsDemo.thrift
 	touch gopath
 
 bin/testclient: gopath
@@ -58,6 +59,7 @@
 
 check: gopath genmock
 	$(GO) test -mod=mod -v ./src/common/...
+	$(GO) test -mod=mod -v ./src/gen/...
 
 genmock: gopath
 	sh genmock.sh
diff --git a/test/go/src/bin/testclient/main.go b/test/go/src/bin/testclient/main.go
index b711958..95fcd47 100644
--- a/test/go/src/bin/testclient/main.go
+++ b/test/go/src/bin/testclient/main.go
@@ -140,6 +140,21 @@
 		}
 	}
 
+	uout := thrift.Tuuid{
+		0x00, 0x11, 0x22, 0x33,
+		0x44, 0x55,
+		0x66, 0x77,
+		0x88, 0x99,
+		0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+	}
+	u, err := client.TestUuid(defaultCtx, uout)
+	if err != nil {
+		t.Fatalf("TestUuid failed with %v", err)
+	}
+	if u != uout {
+		t.Fatalf("Unexpected TestUuid() result expected %v, got %v", uout, u)
+	}
+
 	xs := thrifttest.NewXtruct()
 	xs.StringThing = "thing"
 	xs.ByteThing = 42
diff --git a/test/go/src/common/clientserver_test.go b/test/go/src/common/clientserver_test.go
index 64b326a..a39519d 100644
--- a/test/go/src/common/clientserver_test.go
+++ b/test/go/src/common/clientserver_test.go
@@ -102,6 +102,13 @@
 var defaultCtx = context.Background()
 
 func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, handler *MockThriftTest) {
+	u := thrift.Tuuid{
+		0x00, 0x11, 0x22, 0x33,
+		0x44, 0x55,
+		0x66, 0x77,
+		0x88, 0x99,
+		0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+	}
 	gomock.InOrder(
 		handler.EXPECT().TestVoid(gomock.Any()),
 		handler.EXPECT().TestString(gomock.Any(), "thing").Return("thing", nil),
@@ -111,6 +118,7 @@
 		handler.EXPECT().TestI32(gomock.Any(), int32(4242)).Return(int32(4242), nil),
 		handler.EXPECT().TestI64(gomock.Any(), int64(424242)).Return(int64(424242), nil),
 		// TODO: add TestBinary()
+		handler.EXPECT().TestUuid(gomock.Any(), u).Return(u, nil),
 		handler.EXPECT().TestDouble(gomock.Any(), float64(42.42)).Return(float64(42.42), nil),
 		handler.EXPECT().TestStruct(gomock.Any(), &thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}).Return(&thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}, nil),
 		handler.EXPECT().TestNest(gomock.Any(), &thrifttest.Xtruct2{StructThing: &thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}}).Return(&thrifttest.Xtruct2{StructThing: &thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}}, nil),
@@ -182,6 +190,16 @@
 		t.Errorf("Unexpected TestI64() result expected 424242, got %d ", i64)
 	}
 
+	// TODO: add TestBinary() call
+
+	uret, err := client.TestUuid(defaultCtx, u)
+	if err != nil {
+		t.Errorf("Unexpected error in TestUuid() call: %s", err)
+	}
+	if uret != u {
+		t.Errorf("Unexpected TestUuid() result expected %v, got %v ", uret, u)
+	}
+
 	d, err := client.TestDouble(defaultCtx, 42.42)
 	if err != nil {
 		t.Errorf("Unexpected error in TestDouble() call: %s", err)
@@ -190,8 +208,6 @@
 		t.Errorf("Unexpected TestDouble() result expected 42.42, got %f ", d)
 	}
 
-	// TODO: add TestBinary() call
-
 	xs := thrifttest.NewXtruct()
 	xs.StringThing = "thing"
 	xs.ByteThing = 42
diff --git a/test/go/src/common/printing_handler.go b/test/go/src/common/printing_handler.go
index b726373..0939a01 100644
--- a/test/go/src/common/printing_handler.go
+++ b/test/go/src/common/printing_handler.go
@@ -26,6 +26,8 @@
 	"fmt"
 	"time"
 
+	"github.com/apache/thrift/lib/go/thrift"
+
 	//lint:ignore ST1001 allow dot import here
 	. "github.com/apache/thrift/test/go/src/gen/thrifttest"
 )
@@ -45,7 +47,7 @@
 // @return string - returns the string 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestString(ctx context.Context, thing string) (r string, err error) {
 	fmt.Printf("testString(\"%s\")\n", thing)
 	return thing, nil
@@ -56,7 +58,7 @@
 // @return bool - returns the bool 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestBool(ctx context.Context, thing bool) (r bool, err error) {
 	fmt.Printf("testBool(%t)\n", thing)
 	return thing, nil
@@ -67,7 +69,7 @@
 // @return byte - returns the byte 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestByte(ctx context.Context, thing int8) (r int8, err error) {
 	fmt.Printf("testByte(%d)\n", thing)
 	return thing, nil
@@ -78,7 +80,7 @@
 // @return i32 - returns the i32 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestI32(ctx context.Context, thing int32) (r int32, err error) {
 	fmt.Printf("testI32(%d)\n", thing)
 	return thing, nil
@@ -89,7 +91,7 @@
 // @return i64 - returns the i64 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestI64(ctx context.Context, thing int64) (r int64, err error) {
 	fmt.Printf("testI64(%d)\n", thing)
 	return thing, nil
@@ -100,7 +102,7 @@
 // @return double - returns the double 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestDouble(ctx context.Context, thing float64) (r float64, err error) {
 	fmt.Printf("testDouble(%f)\n", thing)
 	return thing, nil
@@ -111,18 +113,29 @@
 // @return []byte - returns the binary 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestBinary(ctx context.Context, thing []byte) (r []byte, err error) {
 	fmt.Printf("testBinary(%s)\n", hex.EncodeToString(thing))
 	return thing, nil
 }
 
+// Prints 'testUuid("%s")' where '%s' is the uuid given. Note that the uuid byte order should be correct.
+// @param uuid  thing - the uuid to print
+// @return uuid  - returns the uuid 'thing'
+//
+// Parameters:
+//   - Thing
+func (p *printingHandler) TestUuid(ctx context.Context, thing thrift.Tuuid) (r thrift.Tuuid, err error) {
+	fmt.Printf("testUuid(%s)\n", thing.String())
+	return thing, nil
+}
+
 // Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values
 // @param Xtruct thing - the Xtruct to print
 // @return Xtruct - returns the Xtruct 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestStruct(ctx context.Context, thing *Xtruct) (r *Xtruct, err error) {
 	fmt.Printf("testStruct({\"%s\", %d, %d, %d})\n", thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing)
 	return thing, err
@@ -133,7 +146,7 @@
 // @return Xtruct2 - returns the Xtruct2 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestNest(ctx context.Context, nest *Xtruct2) (r *Xtruct2, err error) {
 	thing := nest.StructThing
 	fmt.Printf("testNest({%d, {\"%s\", %d, %d, %d}, %d})\n", nest.ByteThing, thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing, nest.I32Thing)
@@ -141,12 +154,14 @@
 }
 
 // Prints 'testMap("{%s")' where thing has been formatted into a string of  'key => value' pairs
-//  separated by commas and new lines
+//
+//	separated by commas and new lines
+//
 // @param map<i32,i32> thing - the map<i32,i32> to print
 // @return map<i32,i32> - returns the map<i32,i32> 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestMap(ctx context.Context, thing map[int32]int32) (r map[int32]int32, err error) {
 	fmt.Printf("testMap({")
 	first := true
@@ -163,12 +178,14 @@
 }
 
 // Prints 'testStringMap("{%s}")' where thing has been formatted into a string of  'key => value' pairs
-//  separated by commas and new lines
+//
+//	separated by commas and new lines
+//
 // @param map<string,string> thing - the map<string,string> to print
 // @return map<string,string> - returns the map<string,string> 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestStringMap(ctx context.Context, thing map[string]string) (r map[string]string, err error) {
 	fmt.Printf("testStringMap({")
 	first := true
@@ -185,12 +202,14 @@
 }
 
 // Prints 'testSet("{%s}")' where thing has been formatted into a string of  values
-//  separated by commas and new lines
+//
+//	separated by commas and new lines
+//
 // @param set<i32> thing - the set<i32> to print
 // @return set<i32> - returns the set<i32> 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestSet(ctx context.Context, thing []int32) (r []int32, err error) {
 	fmt.Printf("testSet({")
 	first := true
@@ -207,12 +226,14 @@
 }
 
 // Prints 'testList("{%s}")' where thing has been formatted into a string of  values
-//  separated by commas and new lines
+//
+//	separated by commas and new lines
+//
 // @param list<i32> thing - the list<i32> to print
 // @return list<i32> - returns the list<i32> 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestList(ctx context.Context, thing []int32) (r []int32, err error) {
 	fmt.Printf("testList({")
 	for i, v := range thing {
@@ -230,7 +251,7 @@
 // @return Numberz - returns the Numberz 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestEnum(ctx context.Context, thing Numberz) (r Numberz, err error) {
 	fmt.Printf("testEnum(%d)\n", thing)
 	return thing, nil
@@ -241,7 +262,7 @@
 // @return UserId - returns the UserId 'thing'
 //
 // Parameters:
-//  - Thing
+//   - Thing
 func (p *printingHandler) TestTypedef(ctx context.Context, thing UserId) (r UserId, err error) {
 	fmt.Printf("testTypedef(%d)\n", thing)
 	return thing, nil
@@ -250,10 +271,11 @@
 // Prints 'testMapMap("%d")' with hello as '%d'
 // @param i32 hello - the i32 to print
 // @return map<i32,map<i32,i32>> - returns a dictionary with these values:
-//   {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, }
+//
+//	{-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, }
 //
 // Parameters:
-//  - Hello
+//   - Hello
 func (p *printingHandler) TestMapMap(ctx context.Context, hello int32) (r map[int32]map[int32]int32, err error) {
 	fmt.Printf("testMapMap(%d)\n", hello)
 
@@ -267,15 +289,17 @@
 // So you think you've got this all worked, out eh?
 //
 // Creates a the returned map with these values and prints it out:
-//   { 1 => { 2 => argument,
-//            3 => argument,
-//          },
-//     2 => { 6 => <empty Insanity struct>, },
-//   }
+//
+//	{ 1 => { 2 => argument,
+//	         3 => argument,
+//	       },
+//	  2 => { 6 => <empty Insanity struct>, },
+//	}
+//
 // @return map<UserId, map<Numberz,Insanity>> - a map with the above values
 //
 // Parameters:
-//  - Argument
+//   - Argument
 func (p *printingHandler) TestInsanity(ctx context.Context, argument *Insanity) (r map[UserId]map[Numberz]*Insanity, err error) {
 	fmt.Printf("testInsanity()\n")
 	r = make(map[UserId]map[Numberz]*Insanity)
@@ -297,15 +321,16 @@
 // @param Numberz arg4 -
 // @param UserId arg5 -
 // @return Xtruct - returns an Xtruct with StringThing = "Hello2, ByteThing = arg0, I32Thing = arg1
-//    and I64Thing = arg2
+//
+//	and I64Thing = arg2
 //
 // Parameters:
-//  - Arg0
-//  - Arg1
-//  - Arg2
-//  - Arg3
-//  - Arg4
-//  - Arg5
+//   - Arg0
+//   - Arg1
+//   - Arg2
+//   - Arg3
+//   - Arg4
+//   - Arg5
 func (p *printingHandler) TestMulti(ctx context.Context, arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 Numberz, arg5 UserId) (r *Xtruct, err error) {
 	fmt.Printf("testMulti()\n")
 	r = NewXtruct()
@@ -324,7 +349,7 @@
 // else do not throw anything
 //
 // Parameters:
-//  - Arg
+//   - Arg
 func (p *printingHandler) TestException(ctx context.Context, arg string) (err error) {
 	fmt.Printf("testException(%s)\n", arg)
 	switch arg {
@@ -348,8 +373,8 @@
 // @return Xtruct - an Xtruct with StringThing = arg1
 //
 // Parameters:
-//  - Arg0
-//  - Arg1
+//   - Arg0
+//   - Arg1
 func (p *printingHandler) TestMultiException(ctx context.Context, arg0 string, arg1 string) (r *Xtruct, err error) {
 	fmt.Printf("testMultiException(%s, %s)\n", arg0, arg1)
 	switch arg0 {
@@ -378,7 +403,7 @@
 // @param i32 secondsToSleep - the number of seconds to sleep
 //
 // Parameters:
-//  - SecondsToSleep
+//   - SecondsToSleep
 func (p *printingHandler) TestOneway(ctx context.Context, secondsToSleep int32) (err error) {
 	fmt.Printf("testOneway(%d): Sleeping...\n", secondsToSleep)
 	time.Sleep(time.Second * time.Duration(secondsToSleep))
diff --git a/test/go/src/common/simple_handler.go b/test/go/src/common/simple_handler.go
index fb95457..be5bc82 100644
--- a/test/go/src/common/simple_handler.go
+++ b/test/go/src/common/simple_handler.go
@@ -23,6 +23,8 @@
 	"errors"
 	"time"
 
+	"github.com/apache/thrift/lib/go/thrift"
+
 	//lint:ignore ST1001 allow dot import here
 	. "github.com/apache/thrift/test/go/src/gen/thrifttest"
 )
@@ -63,6 +65,10 @@
 	return thing, nil
 }
 
+func (p *simpleHandler) TestUuid(thing thrift.Tuuid) (r thrift.Tuuid, err error) {
+	return thing, nil
+}
+
 func (p *simpleHandler) TestStruct(thing *Xtruct) (r *Xtruct, err error) {
 	return r, err
 }