THRIFT-625: Add support for 'Go'; provided by Aalok Shah.



git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1072478 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 9dbc1c1..8538afa 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -66,4 +66,5 @@
   ocaml \
   js \
   as3 \
-  st
+  st \
+  go
diff --git a/lib/go/Make.deps b/lib/go/Make.deps
new file mode 100644
index 0000000..c233e7e
--- /dev/null
+++ b/lib/go/Make.deps
@@ -0,0 +1,134 @@
+thrift/.install: bufio.install bytes.install container/list.install container/vector.install encoding/base64.install encoding/binary.install fmt.install http.install io.install json.install log.install math.install net.install os.install reflect.install sort.install strconv.install strings.install
+archive/tar.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/archive/tar.a
+archive/zip.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/archive/zip.a
+asn1.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/asn1.a
+big.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/big.a
+bufio.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/bufio.a
+bytes.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/bytes.a
+cmath.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/cmath.a
+compress/flate.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/flate.a
+compress/gzip.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/gzip.a
+compress/zlib.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/compress/zlib.a
+container/heap.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/heap.a
+container/list.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/list.a
+container/ring.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/ring.a
+container/vector.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/container/vector.a
+crypto.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto.a
+crypto/aes.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/aes.a
+crypto/block.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/block.a
+crypto/blowfish.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/blowfish.a
+crypto/cast5.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/cast5.a
+crypto/cipher.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/cipher.a
+crypto/dsa.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/dsa.a
+crypto/elliptic.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/elliptic.a
+crypto/hmac.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/hmac.a
+crypto/md4.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/md4.a
+crypto/md5.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/md5.a
+crypto/ocsp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/ocsp.a
+crypto/rand.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rand.a
+crypto/rc4.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rc4.a
+crypto/ripemd160.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/ripemd160.a
+crypto/rsa.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/rsa.a
+crypto/sha1.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha1.a
+crypto/sha256.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha256.a
+crypto/sha512.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/sha512.a
+crypto/subtle.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/subtle.a
+crypto/tls.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/tls.a
+crypto/twofish.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/twofish.a
+crypto/x509.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/x509.a
+crypto/xtea.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/crypto/xtea.a
+debug/dwarf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/dwarf.a
+debug/macho.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/macho.a
+debug/elf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/elf.a
+debug/gosym.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/gosym.a
+debug/pe.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/pe.a
+debug/proc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/debug/proc.a
+ebnf.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/ebnf.a
+encoding/ascii85.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/ascii85.a
+encoding/base32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/base32.a
+encoding/base64.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/base64.a
+encoding/binary.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/binary.a
+encoding/git85.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/git85.a
+encoding/hex.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/hex.a
+encoding/line.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/line.a
+encoding/pem.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/encoding/pem.a
+exec.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exec.a
+exp/datafmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/datafmt.a
+exp/draw.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/draw.a
+exp/draw/x11.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/draw/x11.a
+exp/eval.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/exp/eval.a
+expvar.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/expvar.a
+flag.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/flag.a
+fmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/fmt.a
+go/ast.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/ast.a
+go/doc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/doc.a
+go/parser.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/parser.a
+go/printer.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/printer.a
+go/scanner.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/scanner.a
+go/token.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/token.a
+go/typechecker.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/go/typechecker.a
+gob.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/gob.a
+hash.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash.a
+hash/adler32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/adler32.a
+hash/crc32.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/crc32.a
+hash/crc64.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/hash/crc64.a
+html.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/html.a
+http.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http.a
+http/pprof.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/http/pprof.a
+image.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image.a
+image/jpeg.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/jpeg.a
+image/png.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/image/png.a
+index/suffixarray.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/index/suffixarray.a
+io.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/io.a
+io/ioutil.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/io/ioutil.a
+json.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/json.a
+log.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/log.a
+math.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/math.a
+mime.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/mime.a
+mime/multipart.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/mime/multipart.a
+net.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net.a
+net/dict.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net/dict.a
+net/textproto.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/net/textproto.a
+netchan.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/netchan.a
+os.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/os.a
+os/signal.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/os/signal.a
+patch.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/patch.a
+path.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/path.a
+rand.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rand.a
+reflect.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/reflect.a
+regexp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/regexp.a
+rpc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rpc.a
+rpc/jsonrpc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/rpc/jsonrpc.a
+runtime.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime.a
+runtime/cgo.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/cgo.a
+runtime/debug.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/debug.a
+runtime/pprof.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/runtime/pprof.a
+scanner.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/scanner.a
+smtp.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/smtp.a
+sort.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/sort.a
+strconv.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/strconv.a
+strings.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/strings.a
+sync.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/sync.a
+syscall.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/syscall.a
+syslog.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/syslog.a
+tabwriter.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/tabwriter.a
+template.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/template.a
+testing.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing.a
+testing/iotest.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/iotest.a
+testing/quick.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/quick.a
+testing/script.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/testing/script.a
+time.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/time.a
+try.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/try.a
+unicode.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/unicode.a
+utf16.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/utf16.a
+utf8.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/utf8.a
+websocket.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/websocket.a
+xml.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/xml.a
+../cmd/cgo.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/cgo.a
+../cmd/ebnflint.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/ebnflint.a
+../cmd/godoc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/godoc.a
+../cmd/gofmt.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/gofmt.a
+../cmd/goinstall.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/goinstall.a
+../cmd/govet.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/govet.a
+../cmd/goyacc.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/goyacc.a
+../cmd/hgpatch.install: ${GOROOT}/pkg/${GOOS}_${GOARCH}/../cmd/hgpatch.a
diff --git a/lib/go/Makefile b/lib/go/Makefile
new file mode 100644
index 0000000..8e81d8d
--- /dev/null
+++ b/lib/go/Makefile
@@ -0,0 +1,64 @@
+# Copyright 2009 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.
+
+# After editing the DIRS= list or adding imports to any Go files
+# in any of those directories, run:
+#
+#	./deps.bash
+#
+# to rebuild the dependency information in Make.deps.
+
+
+include $(GOROOT)/src/Make.inc
+
+all: Make.deps install
+
+DIRS=\
+     thrift/\
+
+TEST=\
+	$(filter-out $(NOTEST),$(DIRS))
+
+
+clean.dirs: $(addsuffix .clean, $(DIRS))
+install.dirs: $(addsuffix .install, $(DIRS))
+nuke.dirs: $(addsuffix .nuke, $(DIRS))
+test.dirs: $(addsuffix .test, $(DIRS))
+check.dirs: $(addsuffix .check, $(DIRS))
+
+%.clean:
+	+cd $* && gomake clean
+
+%.install:
+	+cd $* && gomake install
+
+%.nuke:
+	+cd $* && gomake nuke
+
+%.test:
+	+cd $* && gomake test
+
+%.check:
+	+cd $* && gomake check
+
+clean: clean.dirs
+
+install: install.dirs
+
+test:	test.dirs
+
+check:	check.dirs
+
+#nuke: nuke.dirs
+#	rm -rf "$(GOROOT)"/pkg/thrift.*
+
+echo-dirs:
+	@echo $(DIRS)
+
+Make.deps:
+	./deps.bash
+
+deps:
+	./deps.bash
+
diff --git a/lib/go/deps.bash b/lib/go/deps.bash
new file mode 100644
index 0000000..dabd404
--- /dev/null
+++ b/lib/go/deps.bash
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+# Copyright 2009 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.
+
+OUT="Make.deps"
+TMP="Make.deps.tmp"
+
+if [ -f $OUT ] && ! [ -w $OUT ]; then
+	echo "$0: $OUT is read-only; aborting." 1>&2
+	exit 1
+fi
+
+# Get list of directories from Makefile
+dirs=$(sed '1,/^DIRS=/d; /^$/,$d; s/\\//g' Makefile)
+dirs2=$(sed '1,/^DIRS=/d; /^$/,$d; s/\\//g' $GOROOT/src/pkg/Makefile)
+dirpat=$(echo $dirs $dirs2 | sed 's/ /|/g; s/.*/^(&)$/')
+
+for dir in $dirs; do (
+	cd $dir || exit 1
+
+	sources=$(sed -n 's/\.go\\/.go/p' Makefile)
+	sources=$(ls $sources 2> /dev/null)  # remove .s, .c, etc.
+
+	deps=$(
+		sed -n '/^import.*"/p; /^import[ \t]*(/,/^)/p' $sources /dev/null |
+		cut -d '"' -f2 |
+		egrep "$dirpat" |
+		grep -v "^$dir\$" |
+		sed 's/$/.install/' |
+		sort -u
+	)
+
+	echo $dir.install: $deps
+) done > $TMP
+
+for dir in $dirs2; do (
+  echo $dir.install: \${GOROOT}/pkg/\${GOOS}_\${GOARCH}/${dir}.a
+) done >> $TMP
+
+mv $TMP $OUT
diff --git a/lib/go/thrift/Makefile b/lib/go/thrift/Makefile
new file mode 100644
index 0000000..59f7862
--- /dev/null
+++ b/lib/go/thrift/Makefile
@@ -0,0 +1,58 @@
+# Copyright 2009 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.
+
+include $(GOROOT)/src/Make.inc
+
+TARG=thrift
+GOFILES=\
+        tapplication_exception.go\
+        tbase.go\
+        tbinary_protocol.go\
+        tcompact_protocol.go\
+        tcompare.go\
+        tcontainer.go\
+        texception.go\
+        tfield.go\
+        tframed_transport.go\
+        thttp_client.go\
+        tiostream_transport.go\
+        tlist.go\
+        tjson_protocol.go\
+        tmap.go\
+        tmemory_buffer.go\
+        tmessage.go\
+        tmessagetype.go\
+        tnonblocking_server.go\
+        tnonblocking_server_socket.go\
+        tnonblocking_socket.go\
+        tnonblocking_transport.go\
+        tnumeric.go\
+        tprocessor.go\
+        tprocessor_factory.go\
+        tprotocol.go\
+        tprotocol_exception.go\
+        tprotocol_factory.go\
+        tserver.go\
+        tserver_socket.go\
+        tserver_transport.go\
+        tset.go\
+        tsimple_server.go\
+        tsimple_json_protocol.go\
+        tsocket.go\
+        tstruct.go\
+        ttransport.go\
+        ttransport_exception.go\
+        ttransport_factory.go\
+        ttype.go
+
+DIRS=\
+
+include $(GOROOT)/src/Make.pkg
+
+check:
+	gomake test
+
+-include ../Make.deps
+
+
diff --git a/lib/go/thrift/_testmain.go b/lib/go/thrift/_testmain.go
new file mode 100644
index 0000000..3b0abfb
--- /dev/null
+++ b/lib/go/thrift/_testmain.go
@@ -0,0 +1,68 @@
+package main
+
+import "./_xtest_"
+import "testing"
+import __regexp__ "regexp"
+
+var tests = []testing.InternalTest{
+	{"thrift_test.TestTApplicationException", thrift_test.TestTApplicationException},
+	{"thrift_test.TestReadWriteBinaryProtocol", thrift_test.TestReadWriteBinaryProtocol},
+	{"thrift_test.TestReadWriteCompactProtocol", thrift_test.TestReadWriteCompactProtocol},
+	{"thrift_test.TestTException", thrift_test.TestTException},
+	{"thrift_test.TestFramedTransport", thrift_test.TestFramedTransport},
+	{"thrift_test.TestHttpClient", thrift_test.TestHttpClient},
+	{"thrift_test.TestIOStreamTransport", thrift_test.TestIOStreamTransport},
+	{"thrift_test.TestWriteJSONProtocolBool", thrift_test.TestWriteJSONProtocolBool},
+	{"thrift_test.TestReadJSONProtocolBool", thrift_test.TestReadJSONProtocolBool},
+	{"thrift_test.TestWriteJSONProtocolByte", thrift_test.TestWriteJSONProtocolByte},
+	{"thrift_test.TestReadJSONProtocolByte", thrift_test.TestReadJSONProtocolByte},
+	{"thrift_test.TestWriteJSONProtocolI16", thrift_test.TestWriteJSONProtocolI16},
+	{"thrift_test.TestReadJSONProtocolI16", thrift_test.TestReadJSONProtocolI16},
+	{"thrift_test.TestWriteJSONProtocolI32", thrift_test.TestWriteJSONProtocolI32},
+	{"thrift_test.TestReadJSONProtocolI32", thrift_test.TestReadJSONProtocolI32},
+	{"thrift_test.TestWriteJSONProtocolI64", thrift_test.TestWriteJSONProtocolI64},
+	{"thrift_test.TestReadJSONProtocolI64", thrift_test.TestReadJSONProtocolI64},
+	{"thrift_test.TestWriteJSONProtocolDouble", thrift_test.TestWriteJSONProtocolDouble},
+	{"thrift_test.TestReadJSONProtocolDouble", thrift_test.TestReadJSONProtocolDouble},
+	{"thrift_test.TestWriteJSONProtocolString", thrift_test.TestWriteJSONProtocolString},
+	{"thrift_test.TestReadJSONProtocolString", thrift_test.TestReadJSONProtocolString},
+	{"thrift_test.TestWriteJSONProtocolBinary", thrift_test.TestWriteJSONProtocolBinary},
+	{"thrift_test.TestReadJSONProtocolBinary", thrift_test.TestReadJSONProtocolBinary},
+	{"thrift_test.TestWriteJSONProtocolList", thrift_test.TestWriteJSONProtocolList},
+	{"thrift_test.TestWriteJSONProtocolSet", thrift_test.TestWriteJSONProtocolSet},
+	{"thrift_test.TestWriteJSONProtocolMap", thrift_test.TestWriteJSONProtocolMap},
+	{"thrift_test.TestReadWriteJSONStruct", thrift_test.TestReadWriteJSONStruct},
+	{"thrift_test.TestReadWriteJSONProtocol", thrift_test.TestReadWriteJSONProtocol},
+	{"thrift_test.TestMemoryBuffer", thrift_test.TestMemoryBuffer},
+	{"thrift_test.TestNonblockingTransportServerToClient", thrift_test.TestNonblockingTransportServerToClient},
+	{"thrift_test.TestNonblockingTransportClientToServer", thrift_test.TestNonblockingTransportClientToServer},
+	{"thrift_test.TestNothing", thrift_test.TestNothing},
+	{"thrift_test.TestWriteSimpleJSONProtocolBool", thrift_test.TestWriteSimpleJSONProtocolBool},
+	{"thrift_test.TestReadSimpleJSONProtocolBool", thrift_test.TestReadSimpleJSONProtocolBool},
+	{"thrift_test.TestWriteSimpleJSONProtocolByte", thrift_test.TestWriteSimpleJSONProtocolByte},
+	{"thrift_test.TestReadSimpleJSONProtocolByte", thrift_test.TestReadSimpleJSONProtocolByte},
+	{"thrift_test.TestWriteSimpleJSONProtocolI16", thrift_test.TestWriteSimpleJSONProtocolI16},
+	{"thrift_test.TestReadSimpleJSONProtocolI16", thrift_test.TestReadSimpleJSONProtocolI16},
+	{"thrift_test.TestWriteSimpleJSONProtocolI32", thrift_test.TestWriteSimpleJSONProtocolI32},
+	{"thrift_test.TestReadSimpleJSONProtocolI32", thrift_test.TestReadSimpleJSONProtocolI32},
+	{"thrift_test.TestWriteSimpleJSONProtocolI64", thrift_test.TestWriteSimpleJSONProtocolI64},
+	{"thrift_test.TestReadSimpleJSONProtocolI64", thrift_test.TestReadSimpleJSONProtocolI64},
+	{"thrift_test.TestWriteSimpleJSONProtocolDouble", thrift_test.TestWriteSimpleJSONProtocolDouble},
+	{"thrift_test.TestReadSimpleJSONProtocolDouble", thrift_test.TestReadSimpleJSONProtocolDouble},
+	{"thrift_test.TestWriteSimpleJSONProtocolString", thrift_test.TestWriteSimpleJSONProtocolString},
+	{"thrift_test.TestReadSimpleJSONProtocolString", thrift_test.TestReadSimpleJSONProtocolString},
+	{"thrift_test.TestWriteSimpleJSONProtocolBinary", thrift_test.TestWriteSimpleJSONProtocolBinary},
+	{"thrift_test.TestReadSimpleJSONProtocolBinary", thrift_test.TestReadSimpleJSONProtocolBinary},
+	{"thrift_test.TestWriteSimpleJSONProtocolList", thrift_test.TestWriteSimpleJSONProtocolList},
+	{"thrift_test.TestWriteSimpleJSONProtocolSet", thrift_test.TestWriteSimpleJSONProtocolSet},
+	{"thrift_test.TestWriteSimpleJSONProtocolMap", thrift_test.TestWriteSimpleJSONProtocolMap},
+	{"thrift_test.TestReadWriteSimpleJSONStruct", thrift_test.TestReadWriteSimpleJSONStruct},
+	{"thrift_test.TestReadWriteSimpleJSONProtocol", thrift_test.TestReadWriteSimpleJSONProtocol},
+}
+var benchmarks = []testing.InternalBenchmark{ //
+}
+
+func main() {
+	testing.Main(__regexp__.MatchString, tests)
+	testing.RunBenchmarks(__regexp__.MatchString, benchmarks)
+}
diff --git a/lib/go/thrift/tapplication_exception.go b/lib/go/thrift/tapplication_exception.go
new file mode 100644
index 0000000..fc8bf2e
--- /dev/null
+++ b/lib/go/thrift/tapplication_exception.go
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "os"
+)
+
+const (
+  UNKNOWN_APPLICATION_EXCEPTION  = 0
+  UNKNOWN_METHOD                 = 1
+  INVALID_MESSAGE_TYPE_EXCEPTION = 2
+  WRONG_METHOD_NAME              = 3
+  BAD_SEQUENCE_ID                = 4
+  MISSING_RESULT                 = 5
+  INTERNAL_ERROR                 = 6
+  PROTOCOL_ERROR                 = 7
+)
+
+
+/**
+ * Application level exception
+ *
+ */
+type TApplicationException interface {
+  TException
+  TypeId() int32
+  Read(iprot TProtocol) (TApplicationException, os.Error)
+  Write(oprot TProtocol) os.Error
+}
+
+type tApplicationException struct {
+  TException
+  type_ int32
+}
+
+func NewTApplicationExceptionDefault() TApplicationException {
+  return NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, "UNKNOWN")
+}
+
+func NewTApplicationExceptionType(type_ int32) TApplicationException {
+  return NewTApplicationException(type_, "UNKNOWN")
+}
+
+func NewTApplicationException(type_ int32, message string) TApplicationException {
+  return &tApplicationException{TException: NewTException(message), type_: type_}
+}
+
+func NewTApplicationExceptionMessage(message string) TApplicationException {
+  return NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, message)
+}
+
+func (p *tApplicationException) TypeId() int32 {
+  return p.type_
+}
+
+func (p *tApplicationException) Read(iprot TProtocol) (error TApplicationException, err os.Error) {
+  _, err = iprot.ReadStructBegin()
+  if err != nil {
+    return
+  }
+
+  message := ""
+  type_ := int32(UNKNOWN_APPLICATION_EXCEPTION)
+
+  for {
+    _, ttype, id, err := iprot.ReadFieldBegin()
+    if err != nil {
+      return
+    }
+    if ttype == STOP {
+      break
+    }
+    switch id {
+    case 1:
+      if ttype == STRING {
+        message, err = iprot.ReadString()
+        if err != nil {
+          return
+        }
+      } else {
+        err = SkipDefaultDepth(iprot, ttype)
+        if err != nil {
+          return
+        }
+      }
+      break
+    case 2:
+      if ttype == I32 {
+        type_, err = iprot.ReadI32()
+        if err != nil {
+          return
+        }
+      } else {
+        err = SkipDefaultDepth(iprot, ttype)
+        if err != nil {
+          return
+        }
+      }
+      break
+    default:
+      err = SkipDefaultDepth(iprot, ttype)
+      if err != nil {
+        return
+      }
+      break
+    }
+    err = iprot.ReadFieldEnd()
+    if err != nil {
+      return
+    }
+  }
+  err = iprot.ReadStructEnd()
+  error = NewTApplicationException(type_, message)
+  return
+}
+
+func (p *tApplicationException) Write(oprot TProtocol) (err os.Error) {
+  err = oprot.WriteStructBegin("TApplicationException")
+  if len(p.String()) > 0 {
+    err = oprot.WriteFieldBegin("message", STRING, 1)
+    if err != nil {
+      return
+    }
+    err = oprot.WriteString(p.String())
+    if err != nil {
+      return
+    }
+    err = oprot.WriteFieldEnd()
+    if err != nil {
+      return
+    }
+  }
+  err = oprot.WriteFieldBegin("type", I32, 2)
+  if err != nil {
+    return
+  }
+  err = oprot.WriteI32(p.type_)
+  if err != nil {
+    return
+  }
+  err = oprot.WriteFieldEnd()
+  if err != nil {
+    return
+  }
+  err = oprot.WriteFieldStop()
+  if err != nil {
+    return
+  }
+  err = oprot.WriteStructEnd()
+  return
+}
diff --git a/lib/go/thrift/tapplication_exception_test.go b/lib/go/thrift/tapplication_exception_test.go
new file mode 100644
index 0000000..d9572f4
--- /dev/null
+++ b/lib/go/thrift/tapplication_exception_test.go
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+)
+
+func TestTApplicationException(t *testing.T) {
+  exc := NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, "")
+  if exc.String() != "" {
+    t.Fatalf("Expected empty string for exception but found '%s'", exc.String())
+  }
+  if exc.TypeId() != UNKNOWN_APPLICATION_EXCEPTION {
+    t.Fatalf("Expected type UNKNOWN for exception but found '%s'", exc.TypeId())
+  }
+  exc = NewTApplicationException(WRONG_METHOD_NAME, "junk_method")
+  if exc.String() != "junk_method" {
+    t.Fatalf("Expected 'junk_method' for exception but found '%s'", exc.String())
+  }
+  if exc.TypeId() != WRONG_METHOD_NAME {
+    t.Fatalf("Expected type WRONG_METHOD_NAME for exception but found '%s'", exc.TypeId())
+  }
+}
diff --git a/lib/go/thrift/tbase.go b/lib/go/thrift/tbase.go
new file mode 100644
index 0000000..adc52d0
--- /dev/null
+++ b/lib/go/thrift/tbase.go
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+/**
+ * Generic base interface for generated Thrift objects.
+ *
+ */
+type TBase interface {
+
+  /**
+   * Reads the TObject from the given input protocol
+   *
+   * @param iprot Input protocol
+   */
+  Read(iprot TProtocol) (err TException)
+
+  /**
+   * Writes the objects out to the protocol
+   *
+   * @param oprot Output protocol
+   */
+  Write(oprot TProtocol) (err TException)
+
+  /**
+   * Check if a field is currently set or unset.
+   *
+   * @param field
+   */
+  IsSet(field TField) bool
+
+  /**
+   * Get a field's value by field variable. Primitive types will be wrapped in 
+   * the appropriate "boxed" types.
+   *
+   * @param field
+   */
+  FieldValue(field TField) interface{}
+
+  /**
+   * Set a field's value by field variable. Primitive types must be "boxed" in
+   * the appropriate object wrapper type.
+   *
+   * @param field
+   */
+  SetFieldValue(field TField, value interface{})
+
+  DeepCopy() TBase
+}
diff --git a/lib/go/thrift/tbinary_protocol.go b/lib/go/thrift/tbinary_protocol.go
new file mode 100644
index 0000000..1c88da6
--- /dev/null
+++ b/lib/go/thrift/tbinary_protocol.go
@@ -0,0 +1,493 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "encoding/binary"
+  "math"
+  "strings"
+  "io"
+)
+
+type TBinaryProtocol struct {
+  //TProtocolBase;
+  trans            TTransport
+  _StrictRead      bool
+  _StrictWrite     bool
+  _ReadLength      int
+  _CheckReadLength bool
+}
+
+type TBinaryProtocolFactory struct {
+  _StrictRead  bool
+  _StrictWrite bool
+}
+
+func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol {
+  return NewTBinaryProtocol(t, false, true)
+}
+
+func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol {
+  //return &TBinaryProtocol{TProtocolBase:TProtocolBase{trans:t}, _StrictRead:strictRead, _StrictWrite:strictWrite, _ReadLength:0, _CheckReadLength:false};
+  return &TBinaryProtocol{trans: t, _StrictRead: strictRead, _StrictWrite: strictWrite, _ReadLength: 0, _CheckReadLength: false}
+}
+
+func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory {
+  return NewTBinaryProtocolFactory(false, true)
+}
+
+func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory {
+  return &TBinaryProtocolFactory{_StrictRead: strictRead, _StrictWrite: strictWrite}
+}
+
+func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol {
+  return NewTBinaryProtocol(t, p._StrictRead, p._StrictWrite)
+}
+
+/**
+ * Writing Methods
+ */
+
+func (p *TBinaryProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) TProtocolException {
+  if p._StrictWrite {
+    version := uint32(VERSION_1) | uint32(typeId)
+    e := p.WriteI32(int32(version))
+    if e != nil {
+      return e
+    }
+    e = p.WriteString(name)
+    if e != nil {
+      return e
+    }
+    e = p.WriteI32(seqId)
+    return e
+  } else {
+    e := p.WriteString(name)
+    if e != nil {
+      return e
+    }
+    e = p.WriteByte(byte(typeId))
+    if e != nil {
+      return e
+    }
+    e = p.WriteI32(seqId)
+    return e
+  }
+  return nil
+}
+
+func (p *TBinaryProtocol) WriteMessageEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) WriteStructBegin(name string) TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) WriteStructEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException {
+  e := p.WriteByte(byte(typeId))
+  if e != nil {
+    return e
+  }
+  e = p.WriteI16(id)
+  return e
+}
+
+func (p *TBinaryProtocol) WriteFieldEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) WriteFieldStop() TProtocolException {
+  e := p.WriteByte(STOP)
+  return e
+}
+
+func (p *TBinaryProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException {
+  e := p.WriteByte(byte(keyType))
+  if e != nil {
+    return e
+  }
+  e = p.WriteByte(byte(valueType))
+  if e != nil {
+    return e
+  }
+  e = p.WriteI32(int32(size))
+  return e
+}
+
+func (p *TBinaryProtocol) WriteMapEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) WriteListBegin(elemType TType, size int) TProtocolException {
+  e := p.WriteByte(byte(elemType))
+  if e != nil {
+    return e
+  }
+  e = p.WriteI32(int32(size))
+  return e
+}
+
+func (p *TBinaryProtocol) WriteListEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) WriteSetBegin(elemType TType, size int) TProtocolException {
+  e := p.WriteByte(byte(elemType))
+  if e != nil {
+    return e
+  }
+  e = p.WriteI32(int32(size))
+  return e
+}
+
+func (p *TBinaryProtocol) WriteSetEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) WriteBool(value bool) TProtocolException {
+  if value {
+    return p.WriteByte(1)
+  }
+  return p.WriteByte(0)
+}
+
+func (p *TBinaryProtocol) WriteByte(value byte) TProtocolException {
+  v := []byte{value}
+  _, e := p.trans.Write(v)
+  return NewTProtocolExceptionFromOsError(e)
+}
+
+func (p *TBinaryProtocol) WriteI16(value int16) TProtocolException {
+  h := byte(0xff & (value >> 8))
+  l := byte(0xff & value)
+  v := []byte{h, l}
+  _, e := p.trans.Write(v)
+  return NewTProtocolExceptionFromOsError(e)
+}
+
+func (p *TBinaryProtocol) WriteI32(value int32) TProtocolException {
+  a := byte(0xff & (value >> 24))
+  b := byte(0xff & (value >> 16))
+  c := byte(0xff & (value >> 8))
+  d := byte(0xff & value)
+  v := []byte{a, b, c, d}
+  _, e := p.trans.Write(v)
+  return NewTProtocolExceptionFromOsError(e)
+}
+
+func (p *TBinaryProtocol) WriteI64(value int64) TProtocolException {
+  a := byte(0xff & (value >> 56))
+  b := byte(0xff & (value >> 48))
+  c := byte(0xff & (value >> 40))
+  d := byte(0xff & (value >> 32))
+  e := byte(0xff & (value >> 24))
+  f := byte(0xff & (value >> 16))
+  g := byte(0xff & (value >> 8))
+  h := byte(0xff & value)
+  v := []byte{a, b, c, d, e, f, g, h}
+  _, err := p.trans.Write(v)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TBinaryProtocol) WriteDouble(value float64) TProtocolException {
+  return p.WriteI64(int64(math.Float64bits(value)))
+}
+
+func (p *TBinaryProtocol) WriteString(value string) TProtocolException {
+  return p.WriteBinaryFromReader(strings.NewReader(value), len(value))
+}
+
+func (p *TBinaryProtocol) WriteBinary(value []byte) TProtocolException {
+  e := p.WriteI32(int32(len(value)))
+  if e != nil {
+    return e
+  }
+  _, err := p.trans.Write(value)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TBinaryProtocol) WriteBinaryFromReader(reader io.Reader, size int) TProtocolException {
+  e := p.WriteI32(int32(size))
+  if e != nil {
+    return e
+  }
+  _, err := io.Copyn(p.trans, reader, int64(size))
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+
+/**
+ * Reading methods
+ */
+
+func (p *TBinaryProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) {
+  size, e := p.ReadI32()
+  if e != nil {
+    return "", typeId, 0, NewTProtocolExceptionFromOsError(e)
+  }
+  if size < 0 {
+    typeId = TMessageType(size & 0x0ff)
+    version := int64(int64(size) & VERSION_MASK)
+    if version != VERSION_1 {
+      return name, typeId, seqId, NewTProtocolException(BAD_VERSION, "Bad version in ReadMessageBegin")
+    }
+    name, e = p.ReadString()
+    if e != nil {
+      return name, typeId, seqId, NewTProtocolExceptionFromOsError(e)
+    }
+    seqId, e = p.ReadI32()
+    if e != nil {
+      return name, typeId, seqId, NewTProtocolExceptionFromOsError(e)
+    }
+    return name, typeId, seqId, nil
+  }
+  if p._StrictRead {
+    return name, typeId, seqId, NewTProtocolException(BAD_VERSION, "Missing version in ReadMessageBegin")
+  }
+  name, e2 := p.readStringBody(int(size))
+  if e2 != nil {
+    return name, typeId, seqId, e2
+  }
+  b, e3 := p.ReadByte()
+  if e3 != nil {
+    return name, typeId, seqId, e3
+  }
+  typeId = TMessageType(b)
+  seqId, e4 := p.ReadI32()
+  if e4 != nil {
+    return name, typeId, seqId, e4
+  }
+  return name, typeId, seqId, nil
+}
+
+func (p *TBinaryProtocol) ReadMessageEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) ReadStructBegin() (name string, err TProtocolException) {
+  return
+}
+
+func (p *TBinaryProtocol) ReadStructEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) ReadFieldBegin() (name string, typeId TType, seqId int16, err TProtocolException) {
+  t, err := p.ReadByte()
+  typeId = TType(t)
+  if err != nil {
+    return name, typeId, seqId, err
+  }
+  if t != STOP {
+    seqId, err = p.ReadI16()
+  }
+  return name, typeId, seqId, err
+}
+
+func (p *TBinaryProtocol) ReadFieldEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) ReadMapBegin() (kType, vType TType, size int, err TProtocolException) {
+  k, e := p.ReadByte()
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  kType = TType(k)
+  v, e := p.ReadByte()
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  vType = TType(v)
+  size32, e := p.ReadI32()
+  size = int(size32)
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  return kType, vType, size, nil
+}
+
+func (p *TBinaryProtocol) ReadMapEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) ReadListBegin() (elemType TType, size int, err TProtocolException) {
+  b, e := p.ReadByte()
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  elemType = TType(b)
+  size32, e := p.ReadI32()
+  size = int(size32)
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  return elemType, size, nil
+}
+
+func (p *TBinaryProtocol) ReadListEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) ReadSetBegin() (elemType TType, size int, err TProtocolException) {
+  b, e := p.ReadByte()
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  elemType = TType(b)
+  size32, e := p.ReadI32()
+  size = int(size32)
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  return elemType, size, nil
+}
+
+func (p *TBinaryProtocol) ReadSetEnd() TProtocolException {
+  return nil
+}
+
+func (p *TBinaryProtocol) ReadBool() (bool, TProtocolException) {
+  b, e := p.ReadByte()
+  v := true
+  if b != 1 {
+    v = false
+  }
+  return v, e
+}
+
+func (p *TBinaryProtocol) ReadByte() (value byte, err TProtocolException) {
+  buf := []byte{0}
+  err = p.readAll(buf)
+  return buf[0], err
+}
+
+func (p *TBinaryProtocol) ReadI16() (value int16, err TProtocolException) {
+  buf := []byte{0, 0}
+  err = p.readAll(buf)
+  value = int16(binary.BigEndian.Uint16(buf))
+  return value, err
+}
+
+func (p *TBinaryProtocol) ReadI32() (value int32, err TProtocolException) {
+  buf := []byte{0, 0, 0, 0}
+  err = p.readAll(buf)
+  value = int32(binary.BigEndian.Uint32(buf))
+  return value, err
+}
+
+func (p *TBinaryProtocol) ReadI64() (value int64, err TProtocolException) {
+  buf := []byte{0, 0, 0, 0, 0, 0, 0, 0}
+  err = p.readAll(buf)
+  value = int64(binary.BigEndian.Uint64(buf))
+  return value, err
+}
+
+func (p *TBinaryProtocol) ReadDouble() (value float64, err TProtocolException) {
+  buf := []byte{0, 0, 0, 0, 0, 0, 0, 0}
+  err = p.readAll(buf)
+  value = math.Float64frombits(binary.BigEndian.Uint64(buf))
+  return value, err
+}
+
+func (p *TBinaryProtocol) ReadString() (value string, err TProtocolException) {
+  size, e := p.ReadI32()
+  if e != nil {
+    return "", e
+  }
+  return p.readStringBody(int(size))
+}
+
+func (p *TBinaryProtocol) ReadBinary() ([]byte, TProtocolException) {
+  size, e := p.ReadI32()
+  if e != nil {
+    return nil, e
+  }
+  isize := int(size)
+  e = p.checkReadLength(isize)
+  if e != nil {
+    return nil, e
+  }
+  buf := make([]byte, isize)
+  _, err := p.trans.ReadAll(buf)
+  return buf, NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TBinaryProtocol) Flush() (err TProtocolException) {
+  return NewTProtocolExceptionFromOsError(p.trans.Flush())
+}
+
+func (p *TBinaryProtocol) Skip(fieldType TType) (err TProtocolException) {
+  return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TBinaryProtocol) Transport() TTransport {
+  return p.trans
+}
+
+func (p *TBinaryProtocol) readAll(buf []byte) TProtocolException {
+  e := p.checkReadLength(len(buf))
+  if e != nil {
+    return e
+  }
+  _, err := p.trans.ReadAll(buf)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TBinaryProtocol) setReadLength(readLength int) {
+  p._ReadLength = readLength
+  p._CheckReadLength = true
+}
+
+func (p *TBinaryProtocol) checkReadLength(length int) TProtocolException {
+  if p._CheckReadLength {
+    p._ReadLength = p._ReadLength - length
+    if p._ReadLength < 0 {
+      return NewTProtocolException(UNKNOWN_PROTOCOL_EXCEPTION, "Message length exceeded: "+string(length))
+    }
+  }
+  return nil
+}
+
+func (p *TBinaryProtocol) readStringBody(size int) (value string, err TProtocolException) {
+  if size < 0 {
+    return "", nil
+  }
+  err = p.checkReadLength(size)
+  if err != nil {
+    return "", err
+  }
+  isize := int(size)
+  buf := make([]byte, isize)
+  _, e := p.trans.ReadAll(buf)
+  return string(buf), NewTProtocolExceptionFromOsError(e)
+}
diff --git a/lib/go/thrift/tbinary_protocol_test.go b/lib/go/thrift/tbinary_protocol_test.go
new file mode 100644
index 0000000..b21b248
--- /dev/null
+++ b/lib/go/thrift/tbinary_protocol_test.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+  //"bytes";
+)
+
+
+func TestReadWriteBinaryProtocol(t *testing.T) {
+  ReadWriteProtocolTest(t, NewTBinaryProtocolFactoryDefault())
+}
diff --git a/lib/go/thrift/tcompact_protocol.go b/lib/go/thrift/tcompact_protocol.go
new file mode 100644
index 0000000..9b780f7
--- /dev/null
+++ b/lib/go/thrift/tcompact_protocol.go
@@ -0,0 +1,856 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "container/vector"
+  "encoding/binary"
+  "fmt"
+  "math"
+  "os"
+  "strings"
+)
+
+const (
+  COMPACT_PROTOCOL_ID       = 0x082
+  COMPACT_VERSION           = 1
+  COMPACT_VERSION_MASK      = 0x1f
+  COMPACT_TYPE_MASK         = 0x0E0
+  COMPACT_TYPE_SHIFT_AMOUNT = 5
+)
+
+type TCompactType byte
+
+const (
+  COMPACT_BOOLEAN_TRUE  = 0x01
+  COMPACT_BOOLEAN_FALSE = 0x02
+  COMPACT_BYTE          = 0x03
+  COMPACT_I16           = 0x04
+  COMPACT_I32           = 0x05
+  COMPACT_I64           = 0x06
+  COMPACT_DOUBLE        = 0x07
+  COMPACT_BINARY        = 0x08
+  COMPACT_LIST          = 0x09
+  COMPACT_SET           = 0x0A
+  COMPACT_MAP           = 0x0B
+  COMPACT_STRUCT        = 0x0C
+)
+
+var (
+  _TTypeToCompactType []TCompactType
+  _TSTOP              TField
+)
+
+func init() {
+  _TSTOP = NewTField("", STOP, 0)
+  _TTypeToCompactType = make([]TCompactType, int(UTF16)+1)
+  _TTypeToCompactType[int(STOP)] = STOP
+  _TTypeToCompactType[int(BOOL)] = COMPACT_BOOLEAN_TRUE
+  _TTypeToCompactType[int(BYTE)] = COMPACT_BYTE
+  _TTypeToCompactType[int(I16)] = COMPACT_I16
+  _TTypeToCompactType[int(I32)] = COMPACT_I32
+  _TTypeToCompactType[int(I64)] = COMPACT_I64
+  _TTypeToCompactType[int(DOUBLE)] = COMPACT_DOUBLE
+  _TTypeToCompactType[int(STRING)] = COMPACT_BINARY
+  _TTypeToCompactType[int(LIST)] = COMPACT_LIST
+  _TTypeToCompactType[int(SET)] = COMPACT_SET
+  _TTypeToCompactType[int(MAP)] = COMPACT_MAP
+  _TTypeToCompactType[int(STRUCT)] = COMPACT_STRUCT
+}
+
+type TCompactProtocolFactory struct{}
+
+func NewTCompactProtocolFactory() *TCompactProtocolFactory {
+  return &TCompactProtocolFactory{}
+}
+
+func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol {
+  return NewTCompactProtocol(trans)
+}
+
+type TCompactProtocol struct {
+  trans TTransport
+
+  /** 
+   * Used to keep track of the last field for the current and previous structs,
+   * so we can do the delta stuff.
+   */
+  lastField   *vector.IntVector
+  lastFieldId int
+
+  /** 
+   * If we encounter a boolean field begin, save the TField here so it can 
+   * have the value incorporated.
+   */
+  booleanField TField
+
+  /**
+   * If we read a field header, and it's a boolean field, save the boolean 
+   * value here so that readBool can use it.
+   */
+  boolValue          bool
+  boolValueIsNotNull bool
+}
+
+/**
+ * Create a TCompactProtocol.
+ *
+ * @param transport the TTransport object to read from or write to.
+ */
+func NewTCompactProtocol(trans TTransport) *TCompactProtocol {
+  return &TCompactProtocol{trans: trans, lastField: &vector.IntVector{}}
+}
+
+
+//
+// Public Writing methods.
+//
+
+/**
+ * Write a message header to the wire. Compact Protocol messages contain the
+ * protocol version so we can migrate forwards in the future if need be.
+ */
+func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) TProtocolException {
+  _, err := p.writeByteDirect(COMPACT_PROTOCOL_ID)
+  if err != nil {
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  _, err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK))
+  if err != nil {
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  _, err = p.writeVarint32(seqid)
+  if err != nil {
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  e := p.WriteString(name)
+  return e
+
+}
+
+func (p *TCompactProtocol) WriteMessageEnd() TProtocolException { return nil }
+
+/**
+ * Write a struct begin. This doesn't actually put anything on the wire. We 
+ * use it as an opportunity to put special placeholder markers on the field
+ * stack so we can get the field id deltas correct.
+ */
+func (p *TCompactProtocol) WriteStructBegin(name string) TProtocolException {
+  p.lastField.Push(p.lastFieldId)
+  p.lastFieldId = 0
+  return nil
+}
+
+/**
+ * Write a struct end. This doesn't actually put anything on the wire. We use
+ * this as an opportunity to pop the last field from the current struct off
+ * of the field stack.
+ */
+func (p *TCompactProtocol) WriteStructEnd() TProtocolException {
+  p.lastFieldId = p.lastField.Pop()
+  return nil
+}
+
+func (p *TCompactProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException {
+  if typeId == BOOL {
+    // we want to possibly include the value, so we'll wait.
+    p.booleanField = NewTField(name, typeId, int(id))
+    return nil
+  }
+  _, err := p.writeFieldBeginInternal(name, typeId, id, 0xFF)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+
+/**
+ * The workhorse of writeFieldBegin. It has the option of doing a 
+ * 'type override' of the type header. This is used specifically in the 
+ * boolean field case.
+ */
+func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id int16, typeOverride byte) (int, os.Error) {
+  // short lastField = lastField_.pop();
+
+  // if there's a type override, use that.
+  var typeToWrite byte
+  if typeOverride == 0xFF {
+    typeToWrite = byte(p.getCompactType(typeId))
+  } else {
+    typeToWrite = typeOverride
+  }
+  // check if we can use delta encoding for the field id
+  fieldId := int(id)
+  written := 0
+  if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 {
+    // write them together
+    written, err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite)
+    if err != nil {
+      return written, err
+    }
+  } else {
+    // write them separate
+    n, err := p.writeByteDirect(typeToWrite)
+    if err != nil {
+      return n, err
+    }
+    err = p.WriteI16(id)
+    written = n + 2
+    if err != nil {
+      return written, err
+    }
+  }
+
+  p.lastFieldId = fieldId
+  // p.lastField.Push(field.id);
+  return written, nil
+}
+
+
+func (p *TCompactProtocol) WriteFieldEnd() TProtocolException { return nil }
+
+func (p *TCompactProtocol) WriteFieldStop() TProtocolException {
+  _, err := p.writeByteDirect(STOP)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException {
+  if size == 0 {
+    _, err := p.writeByteDirect(0)
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  _, err := p.writeVarint32(int32(size))
+  if err != nil {
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  _, err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType)))
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TCompactProtocol) WriteMapEnd() TProtocolException { return nil }
+
+/**
+ * Write a list header.
+ */
+func (p *TCompactProtocol) WriteListBegin(elemType TType, size int) TProtocolException {
+  _, err := p.writeCollectionBegin(elemType, size)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TCompactProtocol) WriteListEnd() TProtocolException { return nil }
+
+/**
+ * Write a set header.
+ */
+func (p *TCompactProtocol) WriteSetBegin(elemType TType, size int) TProtocolException {
+  _, err := p.writeCollectionBegin(elemType, size)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TCompactProtocol) WriteSetEnd() TProtocolException { return nil }
+
+func (p *TCompactProtocol) WriteBool(value bool) TProtocolException {
+  v := byte(COMPACT_BOOLEAN_FALSE)
+  if value {
+    v = byte(COMPACT_BOOLEAN_TRUE)
+  }
+  if p.booleanField != nil {
+    // we haven't written the field header yet
+    _, err := p.writeFieldBeginInternal(p.booleanField.Name(), p.booleanField.TypeId(), int16(p.booleanField.Id()), v)
+    p.booleanField = nil
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  // we're not part of a field, so just write the value.
+  _, err := p.writeByteDirect(v)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+/** 
+ * Write a byte. Nothing to see here!
+ */
+func (p *TCompactProtocol) WriteByte(value byte) TProtocolException {
+  _, err := p.writeByteDirect(value)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write an I16 as a zigzag varint.
+ */
+func (p *TCompactProtocol) WriteI16(value int16) TProtocolException {
+  _, err := p.writeVarint32(p.int32ToZigzag(int32(value)))
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write an i32 as a zigzag varint.
+ */
+func (p *TCompactProtocol) WriteI32(value int32) TProtocolException {
+  _, err := p.writeVarint32(p.int32ToZigzag(value))
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write an i64 as a zigzag varint.
+ */
+func (p *TCompactProtocol) WriteI64(value int64) TProtocolException {
+  _, err := p.writeVarint64(p.int64ToZigzag(value))
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write a double to the wire as 8 bytes.
+ */
+func (p *TCompactProtocol) WriteDouble(value float64) TProtocolException {
+  buf := make([]byte, 8)
+  binary.LittleEndian.PutUint64(buf, math.Float64bits(value))
+  _, err := p.trans.Write(buf)
+  return NewTProtocolExceptionFromOsError(err)
+}
+
+/**
+ * Write a string to the wire with a varint size preceeding.
+ */
+func (p *TCompactProtocol) WriteString(value string) TProtocolException {
+  buf := make([]byte, len(value))
+  strings.NewReader(value).Read(buf)
+  return p.WriteBinary(buf)
+}
+
+/**
+ * Write a byte array, using a varint for the size. 
+ */
+func (p *TCompactProtocol) WriteBinary(bin []byte) TProtocolException {
+  _, e := p.writeVarint32(int32(len(bin)))
+  if e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  if len(bin) > 0 {
+    _, e = p.trans.Write(bin)
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  return nil
+}
+
+
+// 
+// Reading methods.
+// 
+
+/**
+ * Read a message header. 
+ */
+func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) {
+  protocolId, err := p.ReadByte()
+  if protocolId != COMPACT_PROTOCOL_ID {
+    s := fmt.Sprintf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId)
+    return "", typeId, seqId, NewTProtocolException(BAD_VERSION, s)
+  }
+  versionAndType, err := p.ReadByte()
+  version := versionAndType & COMPACT_VERSION_MASK
+  typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & 0x03)
+  if err != nil {
+    return
+  }
+  if version != COMPACT_VERSION {
+    s := fmt.Sprintf("Expected version %02x but got %02x", COMPACT_VERSION, version)
+    err = NewTProtocolException(BAD_VERSION, s)
+    return
+  }
+  seqId, e := p.readVarint32()
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  name, err = p.ReadString()
+  return
+}
+
+func (p *TCompactProtocol) ReadMessageEnd() TProtocolException { return nil }
+
+/**
+ * Read a struct begin. There's nothing on the wire for this, but it is our
+ * opportunity to push a new struct begin marker onto the field stack.
+ */
+func (p *TCompactProtocol) ReadStructBegin() (name string, err TProtocolException) {
+  p.lastField.Push(p.lastFieldId)
+  p.lastFieldId = 0
+  return
+}
+
+/**
+ * Doesn't actually consume any wire data, just removes the last field for 
+ * this struct from the field stack.
+ */
+func (p *TCompactProtocol) ReadStructEnd() TProtocolException {
+  // consume the last field we read off the wire.
+  p.lastFieldId = p.lastField.Pop()
+  return nil
+}
+
+/**
+ * Read a field header off the wire. 
+ */
+func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err TProtocolException) {
+  t, err := p.ReadByte()
+  if err != nil {
+    return
+  }
+
+  // if it's a stop, then we can return immediately, as the struct is over.
+  if (t & 0x0f) == STOP {
+    return _TSTOP.Name(), _TSTOP.TypeId(), int16(_TSTOP.Id()), nil
+  }
+
+  // mask off the 4 MSB of the type header. it could contain a field id delta.
+  modifier := int16((t & 0xf0) >> 4)
+  if modifier == 0 {
+    // not a delta. look ahead for the zigzag varint field id.
+    id, err = p.ReadI16()
+    if err != nil {
+      return
+    }
+  } else {
+    // has a delta. add the delta to the last read field id.
+    id = int16(p.lastFieldId) + modifier
+  }
+  typeId, e := p.getTType(TCompactType(t & 0x0f))
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+
+  // if this happens to be a boolean field, the value is encoded in the type
+  if p.isBoolType(t) {
+    // save the boolean value in a special instance variable.
+    p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE)
+    p.boolValueIsNotNull = true
+  }
+
+  // push the new field onto the field stack so we can keep the deltas going.
+  p.lastFieldId = int(id)
+  return
+}
+
+func (p *TCompactProtocol) ReadFieldEnd() TProtocolException { return nil }
+
+/** 
+ * Read a map header off the wire. If the size is zero, skip reading the key
+ * and value type. This means that 0-length maps will yield TMaps without the
+ * "correct" types.
+ */
+func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err TProtocolException) {
+  size32, e := p.readVarint32()
+  size = int(size32)
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  keyAndValueType := byte(STOP)
+  if size != 0 {
+    keyAndValueType, err = p.ReadByte()
+    if err != nil {
+      return
+    }
+  }
+  keyType, _ = p.getTType(TCompactType(keyAndValueType >> 4))
+  valueType, _ = p.getTType(TCompactType(keyAndValueType & 0xf))
+  return
+}
+
+func (p *TCompactProtocol) ReadMapEnd() TProtocolException { return nil }
+
+/**
+ * Read a list header off the wire. If the list size is 0-14, the size will 
+ * be packed into the element type header. If it's a longer list, the 4 MSB
+ * of the element type header will be 0xF, and a varint will follow with the
+ * true size.
+ */
+func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err TProtocolException) {
+  size_and_type, err := p.ReadByte()
+  if err != nil {
+    return
+  }
+  size = int((size_and_type >> 4) & 0x0f)
+  if size == 15 {
+    size2, e := p.readVarint32()
+    if e != nil {
+      err = NewTProtocolExceptionFromOsError(e)
+      return
+    }
+    size = int(size2)
+  }
+  elemType, e := p.getTType(TCompactType(size_and_type))
+  if e != nil {
+    err = NewTProtocolExceptionFromOsError(e)
+    return
+  }
+  return
+}
+
+func (p *TCompactProtocol) ReadListEnd() TProtocolException { return nil }
+
+/**
+ * Read a set header off the wire. If the set size is 0-14, the size will 
+ * be packed into the element type header. If it's a longer set, the 4 MSB
+ * of the element type header will be 0xF, and a varint will follow with the
+ * true size.
+ */
+func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err TProtocolException) {
+  return p.ReadListBegin()
+}
+
+func (p *TCompactProtocol) ReadSetEnd() TProtocolException { return nil }
+
+/**
+ * Read a boolean off the wire. If this is a boolean field, the value should
+ * already have been read during readFieldBegin, so we'll just consume the
+ * pre-stored value. Otherwise, read a byte.
+ */
+func (p *TCompactProtocol) ReadBool() (value bool, err TProtocolException) {
+  if p.boolValueIsNotNull {
+    p.boolValueIsNotNull = false
+    return p.boolValue, nil
+  }
+  v, err := p.ReadByte()
+  return v == COMPACT_BOOLEAN_TRUE, err
+}
+
+/**
+ * Read a single byte off the wire. Nothing interesting here.
+ */
+func (p *TCompactProtocol) ReadByte() (value byte, err TProtocolException) {
+  buf := []byte{0}
+  _, e := p.trans.ReadAll(buf)
+  if e != nil {
+    return 0, NewTProtocolExceptionFromOsError(e)
+  }
+  return buf[0], nil
+}
+
+/**
+ * Read an i16 from the wire as a zigzag varint.
+ */
+func (p *TCompactProtocol) ReadI16() (value int16, err TProtocolException) {
+  v, err := p.ReadI32()
+  return int16(v), err
+}
+
+/**
+ * Read an i32 from the wire as a zigzag varint.
+ */
+func (p *TCompactProtocol) ReadI32() (value int32, err TProtocolException) {
+  v, e := p.readVarint32()
+  if e != nil {
+    return 0, NewTProtocolExceptionFromOsError(e)
+  }
+  value = p.zigzagToInt32(v)
+  return value, nil
+}
+
+/**
+ * Read an i64 from the wire as a zigzag varint.
+ */
+func (p *TCompactProtocol) ReadI64() (value int64, err TProtocolException) {
+  v, e := p.readVarint64()
+  if e != nil {
+    return 0, NewTProtocolExceptionFromOsError(e)
+  }
+  value = p.zigzagToInt64(v)
+  return value, nil
+}
+
+/**
+ * No magic here - just read a double off the wire.
+ */
+func (p *TCompactProtocol) ReadDouble() (value float64, err TProtocolException) {
+  longBits := make([]byte, 8)
+  _, e := p.trans.ReadAll(longBits)
+  if e != nil {
+    return 0.0, NewTProtocolExceptionFromOsError(e)
+  }
+  return math.Float64frombits(p.bytesToUint64(longBits)), nil
+}
+
+/**
+ * Reads a []byte (via readBinary), and then UTF-8 decodes it.
+ */
+func (p *TCompactProtocol) ReadString() (value string, err TProtocolException) {
+  v, e := p.ReadBinary()
+  return string(v), NewTProtocolExceptionFromOsError(e)
+}
+
+/**
+ * Read a []byte from the wire. 
+ */
+func (p *TCompactProtocol) ReadBinary() (value []byte, err TProtocolException) {
+  length, e := p.readVarint32()
+  if e != nil {
+    return []byte{}, NewTProtocolExceptionFromOsError(e)
+  }
+  if length == 0 {
+    return []byte{}, nil
+  }
+
+  buf := make([]byte, length)
+  p.trans.ReadAll(buf)
+  return buf, nil
+}
+
+func (p *TCompactProtocol) Flush() (err TProtocolException) {
+  return NewTProtocolExceptionFromOsError(p.trans.Flush())
+}
+
+func (p *TCompactProtocol) Skip(fieldType TType) (err TProtocolException) {
+  return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TCompactProtocol) Transport() TTransport {
+  return p.trans
+}
+
+//
+// Internal writing methods
+//
+
+/**
+ * Abstract method for writing the start of lists and sets. List and sets on 
+ * the wire differ only by the type indicator.
+ */
+func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, os.Error) {
+  if size <= 14 {
+    return p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType))))
+  }
+  n, err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType)))
+  if err != nil {
+    return n, err
+  }
+  m, err := p.writeVarint32(int32(size))
+  return n + m, err
+}
+
+/**
+ * Write an i32 as a varint. Results in 1-5 bytes on the wire.
+ * TODO(pomack): make a permanent buffer like writeVarint64?
+ */
+func (p *TCompactProtocol) writeVarint32(n int32) (int, os.Error) {
+  i32buf := make([]byte, 5)
+  idx := 0
+  for {
+    if (n & ^0x7F) == 0 {
+      i32buf[idx] = byte(n)
+      idx++
+      // p.writeByteDirect(byte(n));
+      break
+      // return;
+    } else {
+      i32buf[idx] = byte((n & 0x7F) | 0x80)
+      idx++
+      // p.writeByteDirect(byte(((n & 0x7F) | 0x80)));
+      u := uint32(n)
+      n = int32(u >> 7)
+    }
+  }
+  return p.trans.Write(i32buf[0:idx])
+}
+
+/**
+ * Write an i64 as a varint. Results in 1-10 bytes on the wire.
+ */
+func (p *TCompactProtocol) writeVarint64(n int64) (int, os.Error) {
+  varint64out := make([]byte, 10)
+  idx := 0
+  for {
+    if (n & ^0x7F) == 0 {
+      varint64out[idx] = byte(n)
+      idx++
+      break
+    } else {
+      varint64out[idx] = byte((n & 0x7F) | 0x80)
+      idx++
+      u := uint64(n)
+      n = int64(u >> 7)
+    }
+  }
+  return p.trans.Write(varint64out[0:idx])
+}
+
+/**
+ * Convert l into a zigzag long. This allows negative numbers to be 
+ * represented compactly as a varint.
+ */
+func (p *TCompactProtocol) int64ToZigzag(l int64) int64 {
+  return (l << 1) ^ (l >> 63)
+}
+
+/**
+ * Convert l into a zigzag long. This allows negative numbers to be 
+ * represented compactly as a varint.
+ */
+func (p *TCompactProtocol) int32ToZigzag(n int32) int32 {
+  return (n << 1) ^ (n >> 31)
+}
+
+func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) {
+  binary.LittleEndian.PutUint64(buf, n)
+}
+
+func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) {
+  binary.LittleEndian.PutUint64(buf, uint64(n))
+}
+
+/** 
+ * Writes a byte without any possiblity of all that field header nonsense. 
+ * Used internally by other writing methods that know they need to write a byte.
+ */
+func (p *TCompactProtocol) writeByteDirect(b byte) (int, os.Error) {
+  return p.trans.Write([]byte{b})
+}
+
+/** 
+ * Writes a byte without any possiblity of all that field header nonsense.
+ */
+func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, os.Error) {
+  return p.writeByteDirect(byte(n))
+}
+
+
+//
+// Internal reading methods
+//
+
+/**
+ * Read an i32 from the wire as a varint. The MSB of each byte is set
+ * if there is another byte to follow. This can read up to 5 bytes.
+ */
+func (p *TCompactProtocol) readVarint32() (int32, os.Error) {
+  // if the wire contains the right stuff, this will just truncate the i64 we
+  // read and get us the right sign.
+  v, err := p.readVarint64()
+  return int32(v), err
+}
+
+
+/**
+ * Read an i64 from the wire as a proper varint. The MSB of each byte is set 
+ * if there is another byte to follow. This can read up to 10 bytes.
+ */
+func (p *TCompactProtocol) readVarint64() (int64, os.Error) {
+  shift := uint(0)
+  result := int64(0)
+  for {
+    b, err := p.ReadByte()
+    if err != nil {
+      return 0, err
+    }
+    result |= int64(b&0x7f) << shift
+    if (b & 0x80) != 0x80 {
+      break
+    }
+    shift += 7
+  }
+  return result, nil
+}
+
+
+//
+// encoding helpers
+//
+
+/**
+ * Convert from zigzag int to int.
+ */
+func (p *TCompactProtocol) zigzagToInt32(n int32) int32 {
+  u := uint32(n)
+  return int32(u>>1) ^ -(n & 1)
+}
+
+/** 
+ * Convert from zigzag long to long.
+ */
+func (p *TCompactProtocol) zigzagToInt64(n int64) int64 {
+  u := uint64(n)
+  return int64(u>>1) ^ -(n & 1)
+}
+
+/**
+ * Note that it's important that the mask bytes are long literals, 
+ * otherwise they'll default to ints, and when you shift an int left 56 bits,
+ * you just get a messed up int.
+ */
+func (p *TCompactProtocol) bytesToInt64(b []byte) int64 {
+  return int64(binary.LittleEndian.Uint64(b))
+}
+
+/**
+ * Note that it's important that the mask bytes are long literals, 
+ * otherwise they'll default to ints, and when you shift an int left 56 bits,
+ * you just get a messed up int.
+ */
+func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 {
+  return binary.LittleEndian.Uint64(b)
+}
+
+//
+// type testing and converting
+//
+
+func (p *TCompactProtocol) isBoolType(b byte) bool {
+  return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE
+}
+
+/**
+ * Given a TCompactType constant, convert it to its corresponding 
+ * TType value.
+ */
+func (p *TCompactProtocol) getTType(t TCompactType) (TType, os.Error) {
+  switch byte(t) & 0x0f {
+  case STOP:
+    return STOP, nil
+  case COMPACT_BOOLEAN_FALSE:
+  case COMPACT_BOOLEAN_TRUE:
+    return BOOL, nil
+  case COMPACT_BYTE:
+    return BYTE, nil
+  case COMPACT_I16:
+    return I16, nil
+  case COMPACT_I32:
+    return I32, nil
+  case COMPACT_I64:
+    return I64, nil
+  case COMPACT_DOUBLE:
+    return DOUBLE, nil
+  case COMPACT_BINARY:
+    return STRING, nil
+  case COMPACT_LIST:
+    return LIST, nil
+  case COMPACT_SET:
+    return SET, nil
+  case COMPACT_MAP:
+    return MAP, nil
+  case COMPACT_STRUCT:
+    return STRUCT, nil
+  }
+  return STOP, NewTException("don't know what type: " + string(t&0x0f))
+}
+
+/**
+ * Given a TType value, find the appropriate TCompactProtocol.Types constant.
+ */
+func (p *TCompactProtocol) getCompactType(t TType) TCompactType {
+  return _TTypeToCompactType[int(t)]
+}
diff --git a/lib/go/thrift/tcompact_protocol_test.go b/lib/go/thrift/tcompact_protocol_test.go
new file mode 100644
index 0000000..da0e39c
--- /dev/null
+++ b/lib/go/thrift/tcompact_protocol_test.go
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+  //"bytes";
+)
+
+func TestReadWriteCompactProtocol(t *testing.T) {
+  ReadWriteProtocolTest(t, NewTCompactProtocolFactory())
+  /*
+     transports := []TTransport{
+       NewTMemoryBuffer(), 
+       NewTIOStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 16384))),
+       NewTFramedTransport(NewTMemoryBuffer()),
+     }
+     for _, trans := range transports {
+       p := NewTCompactProtocol(trans);
+       ReadWriteBool(t, p, trans);
+       p = NewTCompactProtocol(trans);
+       ReadWriteByte(t, p, trans);
+       p = NewTCompactProtocol(trans);
+       ReadWriteI16(t, p, trans);
+       p = NewTCompactProtocol(trans);
+       ReadWriteI32(t, p, trans);
+       p = NewTCompactProtocol(trans);
+       ReadWriteI64(t, p, trans);
+       p = NewTCompactProtocol(trans);
+       ReadWriteDouble(t, p, trans);
+       p = NewTCompactProtocol(trans);
+       ReadWriteString(t, p, trans);
+       p = NewTCompactProtocol(trans);
+       ReadWriteBinary(t, p, trans);
+       trans.Close();
+     }
+  */
+}
diff --git a/lib/go/thrift/tcompare.go b/lib/go/thrift/tcompare.go
new file mode 100644
index 0000000..01fef44
--- /dev/null
+++ b/lib/go/thrift/tcompare.go
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package thrift
+
+func CompareInt(i, j int) int {
+  if i > j {
+    return 1
+  }
+  if i < j {
+    return -1
+  }
+  return 0
+}
+
+func CompareInt16(i, j int16) int {
+  if i > j {
+    return 1
+  }
+  if i < j {
+    return -1
+  }
+  return 0
+}
+
+func CompareInt32(i, j int32) int {
+  if i > j {
+    return 1
+  }
+  if i < j {
+    return -1
+  }
+  return 0
+}
+
+func CompareInt64(i, j int32) int {
+  if i > j {
+    return 1
+  }
+  if i < j {
+    return -1
+  }
+  return 0
+}
+
+func CompareStringArray(i, j []string) int {
+  if cmp := CompareInt(len(i), len(j)); cmp != 0 {
+    return cmp
+  }
+  size := len(i)
+  for k := 0; k < size; k++ {
+    if cmp := CompareString(i[k], j[k]); cmp != 0 {
+      return cmp
+    }
+  }
+  return 0
+}
+
+func CompareString(i, j string) int {
+  if i > j {
+    return 1
+  }
+  if i < j {
+    return -1
+  }
+  return 0
+}
+
+func CompareFloat(i, j float32) int {
+  if i > j {
+    return 1
+  }
+  if i < j {
+    return -1
+  }
+  return 0
+}
+
+func CompareDouble(i, j float64) int {
+  if i > j {
+    return 1
+  }
+  if i < j {
+    return -1
+  }
+  return 0
+}
+
+func CompareByte(i, j byte) int {
+  if i > j {
+    return 1
+  }
+  if i < j {
+    return -1
+  }
+  return 0
+}
+
+func CompareBool(i, j bool) int {
+  if i {
+    if j {
+      return 0
+    }
+    return 1
+  }
+  if j {
+    return -1
+  }
+  return 0
+}
diff --git a/lib/go/thrift/tcontainer.go b/lib/go/thrift/tcontainer.go
new file mode 100644
index 0000000..9ea3cba
--- /dev/null
+++ b/lib/go/thrift/tcontainer.go
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package thrift
+
+type TContainer interface {
+  Len() int
+  Contains(data interface{}) bool
+  Equals(other interface{}) bool
+  CompareTo(other interface{}) (int, bool)
+}
diff --git a/lib/go/thrift/texception.go b/lib/go/thrift/texception.go
new file mode 100644
index 0000000..be6cbd5
--- /dev/null
+++ b/lib/go/thrift/texception.go
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "os"
+)
+
+/**
+ * Generic exception class for Thrift.
+ *
+ */
+
+type TException interface {
+  String() string
+}
+
+type tException struct {
+  message string
+}
+
+func (p *tException) String() string {
+  return p.message
+}
+
+func NewTException(m string) TException {
+  return &tException{message: m}
+}
+
+func NewTExceptionFromOsError(e os.Error) TException {
+  if e == nil {
+    return nil
+  }
+  t, ok := e.(TException)
+  if ok {
+    return t
+  }
+  return NewTException(e.String())
+}
diff --git a/lib/go/thrift/texception_test.go b/lib/go/thrift/texception_test.go
new file mode 100644
index 0000000..50b3cdd
--- /dev/null
+++ b/lib/go/thrift/texception_test.go
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "os"
+  "testing"
+)
+
+
+func TestTException(t *testing.T) {
+  exc := NewTException("")
+  if exc.String() != "" {
+    t.Fatalf("Expected empty string for exception but found '%s'", exc.String())
+  }
+  exc = NewTExceptionFromOsError(os.EOF)
+  if exc.String() != os.EOF.String() {
+    t.Fatalf("Expected '%s', but found '%s'", os.EOF.String(), exc.String())
+  }
+}
diff --git a/lib/go/thrift/tfield.go b/lib/go/thrift/tfield.go
new file mode 100644
index 0000000..31d9b89
--- /dev/null
+++ b/lib/go/thrift/tfield.go
@@ -0,0 +1,281 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "sort"
+)
+
+/**
+ * Helper class that encapsulates field metadata.
+ *
+ */
+type TField interface {
+  Name() string
+  TypeId() TType
+  Id() int
+  String() string
+  CompareTo(other interface{}) (int, bool)
+  Equals(other interface{}) bool
+}
+
+type tField struct {
+  name   string
+  typeId TType
+  id     int
+}
+
+func NewTFieldDefault() TField {
+  return ANONYMOUS_FIELD
+}
+
+func NewTField(n string, t TType, i int) TField {
+  return &tField{name: n, typeId: t, id: i}
+}
+
+func (p *tField) Name() string {
+  if p == nil {
+    return ""
+  }
+  return p.name
+}
+
+func (p *tField) TypeId() TType {
+  if p == nil {
+    return TType(VOID)
+  }
+  return p.typeId
+}
+
+func (p *tField) Id() int {
+  if p == nil {
+    return -1
+  }
+  return p.id
+}
+
+func (p *tField) String() string {
+  if p == nil {
+    return "<nil>"
+  }
+  return "<TField name:'" + p.name + "' type:" + string(p.typeId) + " field-id:" + string(p.id) + ">"
+}
+
+func (p *tField) CompareTo(other interface{}) (int, bool) {
+  if other == nil {
+    return 1, true
+  }
+  if data, ok := other.(TField); ok {
+    if p.Id() != data.Id() {
+      return CompareInt(p.Id(), data.Id()), true
+    }
+    if p.TypeId() != data.TypeId() {
+      return CompareByte(byte(p.TypeId()), byte(data.TypeId())), true
+    }
+    return CompareString(p.Name(), data.Name()), true
+  }
+  return 0, false
+}
+
+func (p *tField) Equals(other interface{}) bool {
+  if p == nil {
+    return other == nil
+  }
+  if other == nil {
+    return false
+  }
+  if data, ok := other.(TField); ok {
+    return p.TypeId() == data.TypeId() && p.Id() == data.Id()
+  }
+  return false
+}
+
+var ANONYMOUS_FIELD TField
+
+type tFieldArray []TField
+
+func (p tFieldArray) Len() int {
+  return len(p)
+}
+
+func (p tFieldArray) Less(i, j int) bool {
+  return p[i].Id() < p[j].Id()
+}
+
+func (p tFieldArray) Swap(i, j int) {
+  p[i], p[j] = p[j], p[i]
+}
+
+type TFieldContainer interface {
+  TContainer
+  FieldNameFromFieldId(id int) string
+  FieldIdFromFieldName(name string) int
+  FieldFromFieldId(id int) TField
+  FieldFromFieldName(name string) TField
+  At(i int) TField
+  Iter() <-chan TField
+}
+
+type tFieldContainer struct {
+  fields         []TField
+  nameToFieldMap map[string]TField
+  idToFieldMap   map[int]TField
+}
+
+func NewTFieldContainer(fields []TField) TFieldContainer {
+  sortedFields := make([]TField, len(fields))
+  nameToFieldMap := make(map[string]TField)
+  idToFieldMap := make(map[int]TField)
+  for i, field := range fields {
+    sortedFields[i] = field
+    idToFieldMap[field.Id()] = field
+    if field.Name() != "" {
+      nameToFieldMap[field.Name()] = field
+    }
+  }
+  sort.Sort(tFieldArray(sortedFields))
+  return &tFieldContainer{
+    fields:         fields,
+    nameToFieldMap: nameToFieldMap,
+    idToFieldMap:   idToFieldMap,
+  }
+}
+
+func (p *tFieldContainer) FieldNameFromFieldId(id int) string {
+  if field, ok := p.idToFieldMap[id]; ok {
+    return field.Name()
+  }
+  return ""
+}
+
+func (p *tFieldContainer) FieldIdFromFieldName(name string) int {
+  if field, ok := p.nameToFieldMap[name]; ok {
+    return field.Id()
+  }
+  return -1
+}
+
+func (p *tFieldContainer) FieldFromFieldId(id int) TField {
+  if field, ok := p.idToFieldMap[id]; ok {
+    return field
+  }
+  return ANONYMOUS_FIELD
+}
+
+func (p *tFieldContainer) FieldFromFieldName(name string) TField {
+  if field, ok := p.nameToFieldMap[name]; ok {
+    return field
+  }
+  return ANONYMOUS_FIELD
+}
+
+func (p *tFieldContainer) Len() int {
+  return len(p.fields)
+}
+
+func (p *tFieldContainer) At(i int) TField {
+  return p.FieldFromFieldId(i)
+}
+
+func (p *tFieldContainer) Contains(data interface{}) bool {
+  if i, ok := data.(int); ok {
+    for _, field := range p.fields {
+      if field.Id() == i {
+        return true
+      }
+    }
+  } else if i, ok := data.(int16); ok {
+    for _, field := range p.fields {
+      if field.Id() == int(i) {
+        return true
+      }
+    }
+  } else if s, ok := data.(string); ok {
+    for _, field := range p.fields {
+      if field.Name() == s {
+        return true
+      }
+    }
+  } else if f, ok := data.(TField); ok {
+    for _, field := range p.fields {
+      if field.Equals(f) {
+        return true
+      }
+    }
+  }
+  return false
+}
+
+func (p *tFieldContainer) Equals(other interface{}) bool {
+  if other == nil {
+    return false
+  }
+  if data, ok := other.(TFieldContainer); ok {
+    if p.Len() != data.Len() {
+      return false
+    }
+    for _, field := range p.fields {
+      if !data.Contains(field) {
+        return false
+      }
+    }
+    return true
+  }
+  return false
+}
+
+func (p *tFieldContainer) CompareTo(other interface{}) (int, bool) {
+  if other == nil {
+    return 1, true
+  }
+  if data, ok := other.(TFieldContainer); ok {
+    cont, ok2 := data.(*tFieldContainer)
+    if ok2 && p == cont {
+      return 0, true
+    }
+    if cmp := CompareInt(p.Len(), data.Len()); cmp != 0 {
+      return cmp, true
+    }
+    for _, field := range p.fields {
+      if cmp, ok3 := field.CompareTo(data.At(field.Id())); !ok3 || cmp != 0 {
+        return cmp, ok3
+      }
+    }
+    return 0, true
+  }
+  return 0, false
+}
+
+func (p *tFieldContainer) Iter() <-chan TField {
+  c := make(chan TField)
+  go p.iterate(c)
+  return c
+}
+
+func (p *tFieldContainer) iterate(c chan<- TField) {
+  for _, v := range p.fields {
+    c <- v
+  }
+  close(c)
+}
+
+func init() {
+  ANONYMOUS_FIELD = NewTField("", STOP, 0)
+}
diff --git a/lib/go/thrift/tframed_transport.go b/lib/go/thrift/tframed_transport.go
new file mode 100644
index 0000000..52049cb
--- /dev/null
+++ b/lib/go/thrift/tframed_transport.go
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "encoding/binary"
+  "bytes"
+  "os"
+)
+
+
+type TFramedTransport struct {
+  transport   TTransport
+  writeBuffer *bytes.Buffer
+  readBuffer  *bytes.Buffer
+}
+
+type tFramedTransportFactory struct {
+  factory TTransportFactory
+}
+
+func NewTFramedTransportFactory(factory TTransportFactory) TTransportFactory {
+  return &tFramedTransportFactory{factory: factory}
+}
+
+func (p *tFramedTransportFactory) GetTransport(base TTransport) TTransport {
+  return NewTFramedTransport(p.factory.GetTransport(base))
+}
+
+func NewTFramedTransport(transport TTransport) *TFramedTransport {
+  writeBuf := make([]byte, 0, 1024)
+  readBuf := make([]byte, 0, 1024)
+  return &TFramedTransport{transport: transport, writeBuffer: bytes.NewBuffer(writeBuf), readBuffer: bytes.NewBuffer(readBuf)}
+}
+
+func (p *TFramedTransport) Open() os.Error {
+  return p.transport.Open()
+}
+
+func (p *TFramedTransport) IsOpen() bool {
+  return p.transport.IsOpen()
+}
+
+func (p *TFramedTransport) Peek() bool {
+  return p.transport.Peek()
+}
+
+func (p *TFramedTransport) Close() os.Error {
+  return p.transport.Close()
+}
+
+func (p *TFramedTransport) Read(buf []byte) (int, os.Error) {
+  if p.readBuffer.Len() > 0 {
+    got, err := p.readBuffer.Read(buf)
+    if got > 0 {
+      return got, NewTTransportExceptionFromOsError(err)
+    }
+  }
+
+  // Read another frame of data
+  p.readFrame()
+
+  got, err := p.readBuffer.Read(buf)
+  return got, NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TFramedTransport) ReadAll(buf []byte) (int, os.Error) {
+  return ReadAllTransport(p, buf)
+}
+
+func (p *TFramedTransport) Write(buf []byte) (int, os.Error) {
+  n, err := p.writeBuffer.Write(buf)
+  return n, NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TFramedTransport) Flush() os.Error {
+  size := p.writeBuffer.Len()
+  buf := []byte{0, 0, 0, 0}
+  binary.BigEndian.PutUint32(buf, uint32(size))
+  _, err := p.transport.Write(buf)
+  if err != nil {
+    return NewTTransportExceptionFromOsError(err)
+  }
+  if size > 0 {
+    n, err := p.writeBuffer.WriteTo(p.transport)
+    if err != nil {
+      print("Error while flushing write buffer of size ", size, " to transport, only wrote ", n, " bytes: ", err.String(), "\n")
+      return NewTTransportExceptionFromOsError(err)
+    }
+  }
+  err = p.transport.Flush()
+  return NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TFramedTransport) readFrame() (int, os.Error) {
+  buf := []byte{0, 0, 0, 0}
+  _, err := p.transport.ReadAll(buf)
+  if err != nil {
+    return 0, err
+  }
+  size := int(binary.BigEndian.Uint32(buf))
+  if size < 0 {
+    // TODO(pomack) log error
+    return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Read a negative frame size ("+string(size)+")")
+  }
+  if size == 0 {
+    return 0, nil
+  }
+  buf2 := make([]byte, size)
+  n, err := p.transport.ReadAll(buf2)
+  if err != nil {
+    return n, err
+  }
+  p.readBuffer = bytes.NewBuffer(buf2)
+  return size, nil
+}
diff --git a/lib/go/thrift/tframed_transport_test.go b/lib/go/thrift/tframed_transport_test.go
new file mode 100644
index 0000000..566318c
--- /dev/null
+++ b/lib/go/thrift/tframed_transport_test.go
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+)
+
+func TestFramedTransport(t *testing.T) {
+  trans := NewTFramedTransport(NewTMemoryBuffer())
+  TransportTest(t, trans, trans)
+}
diff --git a/lib/go/thrift/thttp_client.go b/lib/go/thrift/thttp_client.go
new file mode 100644
index 0000000..e09ecdf
--- /dev/null
+++ b/lib/go/thrift/thttp_client.go
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "bytes"
+  "http"
+  "os"
+)
+
+
+type THttpClient struct {
+  response           *http.Response
+  url                *http.URL
+  requestBuffer      *bytes.Buffer
+  nsecConnectTimeout int64
+  nsecReadTimeout    int64
+}
+
+type THttpClientTransportFactory struct {
+  url    string
+  isPost bool
+}
+
+func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport {
+  if trans != nil {
+    t, ok := trans.(*THttpClient)
+    if ok && t.url != nil {
+      if t.requestBuffer != nil {
+        t2, _ := NewTHttpPostClient(t.url.String())
+        return t2
+      }
+      t2, _ := NewTHttpClient(t.url.String())
+      return t2
+    }
+  }
+  if p.isPost {
+    s, _ := NewTHttpPostClient(p.url)
+    return s
+  }
+  s, _ := NewTHttpClient(p.url)
+  return s
+}
+
+func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory {
+  return &THttpClientTransportFactory{url: url, isPost: false}
+}
+
+func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory {
+  return &THttpClientTransportFactory{url: url, isPost: true}
+}
+
+
+func NewTHttpClient(url string) (TTransport, os.Error) {
+  response, finalUrl, err := http.Get(url)
+  if err != nil {
+    return nil, err
+  }
+  parsedURL, err := http.ParseURL(finalUrl)
+  if err != nil {
+    return nil, err
+  }
+  return &THttpClient{response: response, url: parsedURL}, nil
+}
+
+func NewTHttpPostClient(url string) (TTransport, os.Error) {
+  parsedURL, err := http.ParseURL(url)
+  if err != nil {
+    return nil, err
+  }
+  buf := make([]byte, 0, 1024)
+  return &THttpClient{url: parsedURL, requestBuffer: bytes.NewBuffer(buf)}, nil
+}
+
+func (p *THttpClient) Open() os.Error {
+  // do nothing
+  return nil
+}
+
+func (p *THttpClient) IsOpen() bool {
+  return p.response != nil || p.requestBuffer != nil
+}
+
+func (p *THttpClient) Peek() bool {
+  return p.IsOpen()
+}
+
+func (p *THttpClient) Close() os.Error {
+  if p.response != nil && p.response.Body != nil {
+    err := p.response.Body.Close()
+    p.response = nil
+    return err
+  }
+  if p.requestBuffer != nil {
+    p.requestBuffer.Reset()
+    p.requestBuffer = nil
+  }
+  return nil
+}
+
+func (p *THttpClient) Read(buf []byte) (int, os.Error) {
+  if p.response == nil {
+    return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.")
+  }
+  n, err := p.response.Body.Read(buf)
+  return n, NewTTransportExceptionFromOsError(err)
+}
+
+func (p *THttpClient) ReadAll(buf []byte) (int, os.Error) {
+  return ReadAllTransport(p, buf)
+}
+
+func (p *THttpClient) Write(buf []byte) (int, os.Error) {
+  n, err := p.requestBuffer.Write(buf)
+  return n, err
+}
+
+func (p *THttpClient) Flush() os.Error {
+  response, err := http.Post(p.url.String(), "application/x-thrift", p.requestBuffer)
+  if err != nil {
+    return NewTTransportExceptionFromOsError(err)
+  }
+  if response.StatusCode != http.StatusOK {
+    // TODO(pomack) log bad response
+    return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "HTTP Response code: "+string(response.StatusCode))
+  }
+  p.response = response
+  return nil
+}
diff --git a/lib/go/thrift/thttp_client_test.go b/lib/go/thrift/thttp_client_test.go
new file mode 100644
index 0000000..1af8cd3
--- /dev/null
+++ b/lib/go/thrift/thttp_client_test.go
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+  "http"
+  "net"
+)
+
+func TestHttpClient(t *testing.T) {
+  addr, err := FindAvailableTCPServerPort(40000)
+  if err != nil {
+    t.Fatalf("Unable to find available tcp port addr: %s", err)
+  }
+  l, err := net.Listen(addr.Network(), addr.String())
+  if err != nil {
+    t.Fatalf("Unable to setup tcp listener on %s: %s", addr.String(), err)
+  }
+  go http.Serve(l, &HTTPEchoServer{})
+  trans, err := NewTHttpPostClient("http://" + addr.String())
+  if err != nil {
+    l.Close()
+    t.Fatalf("Unable to connect to %s: %s", addr.String(), err)
+  }
+  TransportTest(t, trans, trans)
+}
diff --git a/lib/go/thrift/tiostream_transport.go b/lib/go/thrift/tiostream_transport.go
new file mode 100644
index 0000000..5c4beea
--- /dev/null
+++ b/lib/go/thrift/tiostream_transport.go
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "bufio"
+  "io"
+  "os"
+)
+
+/**
+ * This is the most commonly used base transport. It takes an InputStream
+ * and an OutputStream and uses those to perform all transport operations.
+ * This allows for compatibility with all the nice constructs Java already
+ * has to provide a variety of types of streams.
+ *
+ */
+type TIOStreamTransport struct {
+  Reader       io.Reader
+  Writer       io.Writer
+  IsReadWriter bool
+}
+
+type TIOStreamTransportFactory struct {
+  Reader       io.Reader
+  Writer       io.Writer
+  IsReadWriter bool
+}
+
+func (p *TIOStreamTransportFactory) GetTransport(trans TTransport) TTransport {
+  if trans != nil {
+    t, ok := trans.(*TIOStreamTransport)
+    if ok {
+      if t.IsReadWriter {
+        return NewTIOStreamTransportRW(t.Reader.(io.ReadWriter))
+      }
+      if t.Reader != nil && t.Writer != nil {
+        return NewTIOStreamTransportRAndW(t.Reader, t.Writer)
+      }
+      if t.Reader != nil && t.Writer == nil {
+        return NewTIOStreamTransportR(t.Reader)
+      }
+      if t.Reader == nil && t.Writer != nil {
+        return NewTIOStreamTransportW(t.Writer)
+      }
+      return NewTIOStreamTransportDefault()
+    }
+  }
+  if p.IsReadWriter {
+    return NewTIOStreamTransportRW(p.Reader.(io.ReadWriter))
+  }
+  if p.Reader != nil && p.Writer != nil {
+    return NewTIOStreamTransportRAndW(p.Reader, p.Writer)
+  }
+  if p.Reader != nil && p.Writer == nil {
+    return NewTIOStreamTransportR(p.Reader)
+  }
+  if p.Reader == nil && p.Writer != nil {
+    return NewTIOStreamTransportW(p.Writer)
+  }
+  return NewTIOStreamTransportDefault()
+}
+
+func NewTIOStreamTransportFactory(reader io.Reader, writer io.Writer, isReadWriter bool) *TIOStreamTransportFactory {
+  return &TIOStreamTransportFactory{Reader: reader, Writer: writer, IsReadWriter: isReadWriter}
+}
+
+
+/**
+ * Subclasses can invoke the default constructor and then assign the input
+ * streams in the open method.
+ */
+func NewTIOStreamTransportDefault() *TIOStreamTransport {
+  return &TIOStreamTransport{}
+}
+
+/**
+ * Input stream constructor.
+ *
+ * @param is Input stream to read from
+ */
+func NewTIOStreamTransportR(r io.Reader) *TIOStreamTransport {
+  return &TIOStreamTransport{Reader: bufio.NewReader(r)}
+}
+
+/**
+ * Output stream constructor.
+ *
+ * @param os Output stream to read from
+ */
+func NewTIOStreamTransportW(w io.Writer) *TIOStreamTransport {
+  return &TIOStreamTransport{Writer: bufio.NewWriter(w)}
+}
+
+/**
+ * Two-way stream constructor.
+ *
+ * @param is Input stream to read from
+ * @param os Output stream to read from
+ */
+func NewTIOStreamTransportRAndW(r io.Reader, w io.Writer) *TIOStreamTransport {
+  return &TIOStreamTransport{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
+}
+
+/**
+ * Two-way stream constructor.
+ *
+ * @param is Input stream to read from
+ * @param os Output stream to read from
+ */
+func NewTIOStreamTransportRW(rw io.ReadWriter) *TIOStreamTransport {
+  // bufio has a bug where once a Reader hits EOF, a new Write never brings the reader out of EOF
+  // even if reader and writer use the same underlier
+  //bufrw := bufio.NewReadWriter(bufio.NewReader(rw), bufio.NewWriter(rw));
+  return &TIOStreamTransport{Reader: rw, Writer: rw, IsReadWriter: true}
+}
+
+/**
+ * The streams must already be open at construction time, so this should
+ * always return true.
+ *
+ * @return true
+ */
+func (p *TIOStreamTransport) IsOpen() bool {
+  return true
+}
+
+/**
+ * The streams must already be open. This method does nothing.
+ */
+func (p *TIOStreamTransport) Open() os.Error {
+  return nil
+}
+
+func (p *TIOStreamTransport) Peek() bool {
+  return p.IsOpen()
+}
+
+/**
+ * Closes both the input and output streams.
+ */
+func (p *TIOStreamTransport) Close() os.Error {
+  closedReader := false
+  if p.Reader != nil {
+    c, ok := p.Reader.(io.Closer)
+    if ok {
+      e := c.Close()
+      closedReader = true
+      if e != nil {
+        LOGGER.Print("Error closing input stream.", e)
+      }
+    }
+    p.Reader = nil
+  }
+  if p.Writer != nil && (!closedReader || !p.IsReadWriter) {
+    c, ok := p.Writer.(io.Closer)
+    if ok {
+      e := c.Close()
+      if e != nil {
+        LOGGER.Print("Error closing output stream.", e)
+      }
+    }
+    p.Writer = nil
+  }
+  return nil
+}
+
+/**
+ * Reads from the underlying input stream if not null.
+ */
+func (p *TIOStreamTransport) Read(buf []byte) (int, os.Error) {
+  if p.Reader == nil {
+    return 0, NewTTransportException(NOT_OPEN, "Cannot read from null inputStream")
+  }
+  n, err := p.Reader.Read(buf)
+  return n, NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TIOStreamTransport) ReadAll(buf []byte) (int, os.Error) {
+  return ReadAllTransport(p, buf)
+}
+
+
+/**
+ * Writes to the underlying output stream if not null.
+ */
+func (p *TIOStreamTransport) Write(buf []byte) (int, os.Error) {
+  if p.Writer == nil {
+    LOGGER.Print("Could not write to iostream as Writer is null\n")
+    return 0, NewTTransportException(NOT_OPEN, "Cannot write to null outputStream")
+  }
+  n, err := p.Writer.Write(buf)
+  if n == 0 || err != nil {
+    LOGGER.Print("Error writing to iostream, only wrote ", n, " bytes: ", err.String(), "\n")
+  }
+  return n, NewTTransportExceptionFromOsError(err)
+}
+
+/**
+ * Flushes the underlying output stream if not null.
+ */
+func (p *TIOStreamTransport) Flush() os.Error {
+  if p.Writer == nil {
+    return NewTTransportException(NOT_OPEN, "Cannot flush null outputStream")
+  }
+  f, ok := p.Writer.(Flusher)
+  if ok {
+    err := f.Flush()
+    if err != nil {
+      return NewTTransportExceptionFromOsError(err)
+    }
+  }
+  return nil
+}
diff --git a/lib/go/thrift/tiostream_transport_test.go b/lib/go/thrift/tiostream_transport_test.go
new file mode 100644
index 0000000..a7425c7
--- /dev/null
+++ b/lib/go/thrift/tiostream_transport_test.go
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+  "bytes"
+)
+
+func TestIOStreamTransport(t *testing.T) {
+  trans := NewTIOStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 1024)))
+  TransportTest(t, trans, trans)
+}
diff --git a/lib/go/thrift/tjson_protocol.go b/lib/go/thrift/tjson_protocol.go
new file mode 100644
index 0000000..45ab700
--- /dev/null
+++ b/lib/go/thrift/tjson_protocol.go
@@ -0,0 +1,537 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "encoding/base64"
+  "fmt"
+)
+
+const (
+  THRIFT_JSON_PROTOCOL_VERSION = 1
+)
+
+// for references to _ParseContext see tsimplejson_protocol.go
+
+/**
+ * JSON protocol implementation for thrift.
+ *
+ * This protocol produces/consumes a simple output format
+ * suitable for parsing by scripting languages.  It should not be
+ * confused with the full-featured TJSONProtocol.
+ *
+ */
+type TJSONProtocol struct {
+  *TSimpleJSONProtocol
+}
+
+/**
+ * Constructor
+ */
+func NewTJSONProtocol(t TTransport) *TJSONProtocol {
+  v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)}
+  v.parseContextStack.Push(int(_CONTEXT_IN_TOPLEVEL))
+  v.dumpContext.Push(int(_CONTEXT_IN_TOPLEVEL))
+  return v
+}
+
+/**
+ * Factory
+ */
+type TJSONProtocolFactory struct{}
+
+func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol {
+  return NewTJSONProtocol(trans)
+}
+
+func NewTJSONProtocolFactory() *TJSONProtocolFactory {
+  return &TJSONProtocolFactory{}
+}
+
+
+func (p *TJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) TProtocolException {
+  if e := p.OutputListBegin(); e != nil {
+    return e
+  }
+  if e := p.WriteI32(THRIFT_JSON_PROTOCOL_VERSION); e != nil {
+    return e
+  }
+  if e := p.WriteString(name); e != nil {
+    return e
+  }
+  if e := p.WriteByte(byte(typeId)); e != nil {
+    return e
+  }
+  if e := p.WriteI32(seqId); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TJSONProtocol) WriteMessageEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteStructBegin(name string) TProtocolException {
+  if e := p.OutputObjectBegin(); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TJSONProtocol) WriteStructEnd() TProtocolException {
+  return p.OutputObjectEnd()
+}
+
+func (p *TJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException {
+  if e := p.WriteI16(id); e != nil {
+    return e
+  }
+  if e := p.OutputObjectBegin(); e != nil {
+    return e
+  }
+  if e := p.WriteString(p.TypeIdToString(typeId)); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TJSONProtocol) WriteFieldEnd() TProtocolException {
+  return p.OutputObjectEnd()
+}
+
+func (p *TJSONProtocol) WriteFieldStop() TProtocolException { return nil }
+
+func (p *TJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException {
+  if e := p.OutputListBegin(); e != nil {
+    return e
+  }
+  if e := p.WriteString(p.TypeIdToString(keyType)); e != nil {
+    return e
+  }
+  if e := p.WriteString(p.TypeIdToString(valueType)); e != nil {
+    return e
+  }
+  return p.WriteI64(int64(size))
+}
+
+func (p *TJSONProtocol) WriteMapEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteListBegin(elemType TType, size int) TProtocolException {
+  return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TJSONProtocol) WriteListEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteSetBegin(elemType TType, size int) TProtocolException {
+  return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TJSONProtocol) WriteSetEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TJSONProtocol) WriteBool(b bool) TProtocolException {
+  return p.OutputBool(b)
+}
+
+func (p *TJSONProtocol) WriteByte(b byte) TProtocolException {
+  return p.WriteI32(int32(b))
+}
+
+func (p *TJSONProtocol) WriteI16(v int16) TProtocolException {
+  return p.WriteI32(int32(v))
+}
+
+func (p *TJSONProtocol) WriteI32(v int32) TProtocolException {
+  return p.OutputI64(int64(v))
+}
+
+func (p *TJSONProtocol) WriteI64(v int64) TProtocolException {
+  return p.OutputI64(int64(v))
+}
+
+func (p *TJSONProtocol) WriteDouble(v float64) TProtocolException {
+  return p.OutputF64(v)
+}
+
+func (p *TJSONProtocol) WriteString(v string) TProtocolException {
+  return p.OutputString(v)
+}
+
+func (p *TJSONProtocol) WriteBinary(v []byte) TProtocolException {
+  // JSON library only takes in a string, 
+  // not an arbitrary byte array, to ensure bytes are transmitted
+  // efficiently we must convert this into a valid JSON string
+  // therefore we use base64 encoding to avoid excessive escaping/quoting
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  p.writer.Write(JSON_QUOTE_BYTES)
+  writer := base64.NewEncoder(base64.StdEncoding, p.writer)
+  if _, e := writer.Write(v); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  writer.Close()
+  p.writer.Write(JSON_QUOTE_BYTES)
+  return p.OutputPostValue()
+}
+
+/**
+ * Reading methods.
+ */
+
+func (p *TJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) {
+  if isNull, err := p.ParseListBegin(); isNull || err != nil {
+    return name, typeId, seqId, err
+  }
+  version, err := p.ReadI32()
+  if err != nil {
+    return name, typeId, seqId, err
+  }
+  if version != THRIFT_JSON_PROTOCOL_VERSION {
+    return name, typeId, seqId, NewTProtocolException(INVALID_DATA, fmt.Sprint("Unknown Protocol version ", version, ", expected version ", THRIFT_JSON_PROTOCOL_VERSION, "\n"))
+  }
+  if name, err = p.ReadString(); err != nil {
+    return name, typeId, seqId, err
+  }
+  bTypeId, err := p.ReadByte()
+  typeId = TMessageType(bTypeId)
+  if err != nil {
+    return name, typeId, seqId, err
+  }
+  if seqId, err = p.ReadI32(); err != nil {
+    return name, typeId, seqId, err
+  }
+  return name, typeId, seqId, nil
+}
+
+func (p *TJSONProtocol) ReadMessageEnd() TProtocolException {
+  err := p.ParseListEnd()
+  return err
+}
+
+func (p *TJSONProtocol) ReadStructBegin() (name string, err TProtocolException) {
+  _, err = p.ParseObjectStart()
+  return "", err
+}
+
+func (p *TJSONProtocol) ReadStructEnd() TProtocolException {
+  return p.ParseObjectEnd()
+}
+
+func (p *TJSONProtocol) ReadFieldBegin() (string, TType, int16, TProtocolException) {
+  if p.reader.Buffered() < 1 {
+    return "", STOP, -1, nil
+  }
+  b, _ := p.reader.Peek(1)
+  if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] {
+    return "", STOP, -1, nil
+  }
+  fieldId, err := p.ReadI16()
+  if err != nil {
+    return "", STOP, fieldId, err
+  }
+  if _, err = p.ParseObjectStart(); err != nil {
+    return "", STOP, fieldId, err
+  }
+  sType, err := p.ReadString()
+  fType := p.StringToTypeId(sType)
+  return "", fType, fieldId, err
+}
+
+func (p *TJSONProtocol) ReadFieldEnd() TProtocolException {
+  return p.ParseObjectEnd()
+}
+
+func (p *TJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e TProtocolException) {
+  if isNull, e := p.ParseListBegin(); isNull || e != nil {
+    return VOID, VOID, 0, e
+  }
+
+  // read keyType
+  sKeyType, e := p.ReadString()
+  keyType = p.StringToTypeId(sKeyType)
+  if e != nil {
+    return keyType, valueType, size, e
+  }
+
+  // read valueType
+  sValueType, e := p.ReadString()
+  valueType = p.StringToTypeId(sValueType)
+  if e != nil {
+    return keyType, valueType, size, e
+  }
+
+  // read size
+  iSize, err := p.ReadI64()
+  size = int(iSize)
+  return keyType, valueType, size, err
+}
+
+func (p *TJSONProtocol) ReadMapEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TJSONProtocol) ReadListBegin() (elemType TType, size int, e TProtocolException) {
+  return p.ParseElemListBegin()
+}
+
+func (p *TJSONProtocol) ReadListEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TJSONProtocol) ReadSetBegin() (elemType TType, size int, e TProtocolException) {
+  return p.ParseElemListBegin()
+}
+
+func (p *TJSONProtocol) ReadSetEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TJSONProtocol) ReadBool() (bool, TProtocolException) {
+  var value bool
+  if err := p.ParsePreValue(); err != nil {
+    return value, err
+  }
+  b, _ := p.reader.Peek(len(JSON_FALSE))
+  if len(b) > 0 {
+    switch b[0] {
+    case JSON_TRUE[0]:
+      if string(b[0:len(JSON_TRUE)]) == string(JSON_TRUE) {
+        p.reader.Read(b[0:len(JSON_TRUE)])
+        value = true
+      } else {
+        return value, NewTProtocolException(INVALID_DATA, "Expected \"true\" but found: "+string(b))
+      }
+      break
+    case JSON_FALSE[0]:
+      if string(b[0:len(JSON_FALSE)]) == string(JSON_FALSE) {
+        p.reader.Read(b[0:len(JSON_FALSE)])
+        value = false
+      } else {
+        return value, NewTProtocolException(INVALID_DATA, "Expected \"false\" but found: "+string(b))
+      }
+      break
+    case JSON_NULL[0]:
+      if string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+        p.reader.Read(b[0:len(JSON_NULL)])
+        value = false
+      } else {
+        return value, NewTProtocolException(INVALID_DATA, "Expected \"null\" but found: "+string(b))
+      }
+    default:
+      return value, NewTProtocolException(INVALID_DATA, "Expected \"true\", \"false\", or \"null\" but found: "+string(b))
+    }
+  }
+  return value, p.ParsePostValue()
+}
+
+func (p *TJSONProtocol) ReadByte() (byte, TProtocolException) {
+  v, err := p.ReadI64()
+  return byte(v), err
+}
+
+func (p *TJSONProtocol) ReadI16() (int16, TProtocolException) {
+  v, err := p.ReadI64()
+  return int16(v), err
+}
+
+func (p *TJSONProtocol) ReadI32() (int32, TProtocolException) {
+  v, err := p.ReadI64()
+  return int32(v), err
+}
+
+func (p *TJSONProtocol) ReadI64() (int64, TProtocolException) {
+  v, _, err := p.ParseI64()
+  return v, err
+}
+
+func (p *TJSONProtocol) ReadDouble() (float64, TProtocolException) {
+  v, _, err := p.ParseF64()
+  return v, err
+}
+
+func (p *TJSONProtocol) ReadString() (string, TProtocolException) {
+  var v string
+  if err := p.ParsePreValue(); err != nil {
+    return v, err
+  }
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) > 0 && b[0] == JSON_QUOTE {
+    p.reader.ReadByte()
+    value, err := p.ParseStringBody()
+    v = value
+    if err != nil {
+      return v, err
+    }
+  } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+    _, err := p.reader.Read(b[0:len(JSON_NULL)])
+    if err != nil {
+      return v, NewTProtocolExceptionFromOsError(err)
+    }
+  } else {
+    return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b)))
+  }
+  return v, p.ParsePostValue()
+}
+
+func (p *TJSONProtocol) ReadBinary() ([]byte, TProtocolException) {
+  var v []byte
+  if err := p.ParsePreValue(); err != nil {
+    return nil, err
+  }
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) > 0 && b[0] == JSON_QUOTE {
+    p.reader.ReadByte()
+    value, err := p.ParseBase64EncodedBody()
+    v = value
+    if err != nil {
+      return v, err
+    }
+  } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+    _, err := p.reader.Read(b[0:len(JSON_NULL)])
+    if err != nil {
+      return v, NewTProtocolExceptionFromOsError(err)
+    }
+  } else {
+    return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b)))
+  }
+  return v, p.ParsePostValue()
+}
+
+func (p *TJSONProtocol) Flush() (err TProtocolException) {
+  return NewTProtocolExceptionFromOsError(p.writer.Flush())
+}
+
+func (p *TJSONProtocol) Skip(fieldType TType) (err TProtocolException) {
+  return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TJSONProtocol) Transport() TTransport {
+  return p.trans
+}
+
+func (p *TJSONProtocol) readElemListBegin() (elemType TType, size int, e TProtocolException) {
+  if isNull, e := p.ParseListBegin(); isNull || e != nil {
+    return VOID, 0, e
+  }
+  sElemType, err := p.ReadString()
+  elemType = p.StringToTypeId(sElemType)
+  if err != nil {
+    return elemType, size, err
+  }
+  nSize, err2 := p.ReadI64()
+  size = int(nSize)
+  return elemType, size, err2
+}
+
+func (p *TJSONProtocol) writeElemListBegin(elemType TType, size int) TProtocolException {
+  if e := p.OutputListBegin(); e != nil {
+    return e
+  }
+  if e := p.OutputString(p.TypeIdToString(elemType)); e != nil {
+    return e
+  }
+  if e := p.OutputI64(int64(size)); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TJSONProtocol) TypeIdToString(fieldType TType) string {
+  switch byte(fieldType) {
+  case STOP:
+    return "stp"
+  case VOID:
+    return "v"
+  case BOOL:
+    return "tf"
+  case BYTE:
+    return "i8"
+  case DOUBLE:
+    return "dbl"
+  case I16:
+    return "i16"
+  case I32:
+    return "i32"
+  case I64:
+    return "i64"
+  case STRING:
+    return "str"
+  case STRUCT:
+    return "rec"
+  case MAP:
+    return "map"
+  case SET:
+    return "set"
+  case LIST:
+    return "lst"
+  case ENUM:
+    return "i32"
+  case UTF16:
+    return "str"
+  case GENERIC:
+    return "gen"
+  }
+  return ""
+}
+
+func (p *TJSONProtocol) StringToTypeId(fieldType string) TType {
+  switch fieldType {
+  case "stp":
+    return TType(STOP)
+  case "v":
+    return TType(VOID)
+  case "tf":
+    return TType(BOOL)
+  case "i8":
+    return TType(BYTE)
+  case "dbl":
+    return TType(DOUBLE)
+  case "16":
+    return TType(I16)
+  case "i32":
+    return TType(I32)
+  case "i64":
+    return TType(I64)
+  case "str":
+    return TType(STRING)
+  case "rec":
+    return TType(STRUCT)
+  case "map":
+    return TType(MAP)
+  case "set":
+    return TType(SET)
+  case "lst":
+    return TType(LIST)
+  case "enm":
+    return TType(ENUM)
+  case "u16":
+    return TType(UTF16)
+  case "gen":
+    return TType(GENERIC)
+  }
+  return TType(STOP)
+}
diff --git a/lib/go/thrift/tjson_protocol_test.go b/lib/go/thrift/tjson_protocol_test.go
new file mode 100644
index 0000000..60f0f2e
--- /dev/null
+++ b/lib/go/thrift/tjson_protocol_test.go
@@ -0,0 +1,674 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "encoding/base64"
+  "fmt"
+  "json"
+  "math"
+  "strconv"
+  "testing"
+)
+
+func TestWriteJSONProtocolBool(t *testing.T) {
+  thetype := "boolean"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  for _, value := range BOOL_VALUES {
+    if e := p.WriteBool(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := false
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadJSONProtocolBool(t *testing.T) {
+  thetype := "boolean"
+  for _, value := range BOOL_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTJSONProtocol(trans)
+    if value {
+      trans.Write(JSON_TRUE)
+    } else {
+      trans.Write(JSON_FALSE)
+    }
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadBool()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteJSONProtocolByte(t *testing.T) {
+  thetype := "byte"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  for _, value := range BYTE_VALUES {
+    if e := p.WriteByte(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := byte(0)
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadJSONProtocolByte(t *testing.T) {
+  thetype := "byte"
+  for _, value := range BYTE_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTJSONProtocol(trans)
+    trans.WriteString(strconv.Itoa(int(value)))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadByte()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteJSONProtocolI16(t *testing.T) {
+  thetype := "int16"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  for _, value := range INT16_VALUES {
+    if e := p.WriteI16(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := int16(0)
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadJSONProtocolI16(t *testing.T) {
+  thetype := "int16"
+  for _, value := range INT16_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTJSONProtocol(trans)
+    trans.WriteString(strconv.Itoa(int(value)))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadI16()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteJSONProtocolI32(t *testing.T) {
+  thetype := "int32"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  for _, value := range INT32_VALUES {
+    if e := p.WriteI32(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := int32(0)
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadJSONProtocolI32(t *testing.T) {
+  thetype := "int32"
+  for _, value := range INT32_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTJSONProtocol(trans)
+    trans.WriteString(strconv.Itoa(int(value)))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadI32()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteJSONProtocolI64(t *testing.T) {
+  thetype := "int64"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  for _, value := range INT64_VALUES {
+    if e := p.WriteI64(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := int64(0)
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadJSONProtocolI64(t *testing.T) {
+  thetype := "int64"
+  for _, value := range INT64_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTJSONProtocol(trans)
+    trans.WriteString(strconv.Itoa64(value))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadI64()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteJSONProtocolDouble(t *testing.T) {
+  thetype := "double"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  for _, value := range DOUBLE_VALUES {
+    if e := p.WriteDouble(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if math.IsInf(value, 1) {
+      if s != JsonQuote(JSON_INFINITY) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_INFINITY))
+      }
+    } else if math.IsInf(value, -1) {
+      if s != JsonQuote(JSON_NEGATIVE_INFINITY) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_NEGATIVE_INFINITY))
+      }
+    } else if math.IsNaN(value) {
+      if s != JsonQuote(JSON_NAN) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_NAN))
+      }
+    } else {
+      if s != fmt.Sprint(value) {
+        t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+      }
+      v := float64(0)
+      if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+      }
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadJSONProtocolDouble(t *testing.T) {
+  thetype := "double"
+  for _, value := range DOUBLE_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTJSONProtocol(trans)
+    n := NewNumericFromDouble(value)
+    trans.WriteString(n.String())
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadDouble()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if math.IsInf(value, 1) {
+      if !math.IsInf(v, 1) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v)
+      }
+    } else if math.IsInf(value, -1) {
+      if !math.IsInf(v, -1) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v)
+      }
+    } else if math.IsNaN(value) {
+      if !math.IsNaN(v) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v)
+      }
+    } else {
+      if v != value {
+        t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+      }
+      if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+      }
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteJSONProtocolString(t *testing.T) {
+  thetype := "string"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  for _, value := range STRING_VALUES {
+    if e := p.WriteString(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s[0] != '"' || s[len(s)-1] != '"' {
+      t.Fatalf("Bad value for %s '%v', wrote '%v', expected: %v", thetype, value, s, fmt.Sprint("\"", value, "\""))
+    }
+    v := new(string)
+    if err := json.Unmarshal([]byte(s), v); err != nil || *v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadJSONProtocolString(t *testing.T) {
+  thetype := "string"
+  for _, value := range STRING_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTJSONProtocol(trans)
+    trans.WriteString(JsonQuote(value))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadString()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    v1 := new(string)
+    if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteJSONProtocolBinary(t *testing.T) {
+  thetype := "binary"
+  value := protocol_bdata
+  b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata)))
+  base64.StdEncoding.Encode(b64value, value)
+  b64String := string(b64value)
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  if e := p.WriteBinary(value); e != nil {
+    t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+  }
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+  }
+  s := trans.String()
+  expectedString := fmt.Sprint("\"", b64String, "\"")
+  if s != expectedString {
+    t.Fatalf("Bad value for %s %v\n  wrote:  \"%v\"\nexpected: \"%v\"", thetype, value, s, expectedString)
+  }
+  v1, err := p.ReadBinary()
+  if err != nil {
+    t.Fatalf("Unable to read binary: %s", err.String())
+  }
+  if len(v1) != len(value) {
+    t.Fatalf("Invalid value for binary\nexpected: \"%v\"\n   read: \"%v\"", value, v1)
+  }
+  for k, v := range value {
+    if v1[k] != v {
+      t.Fatalf("Invalid value for binary at %v\nexpected: \"%v\"\n   read: \"%v\"", k, v, v1[k])
+    }
+  }
+  trans.Close()
+}
+
+func TestReadJSONProtocolBinary(t *testing.T) {
+  thetype := "binary"
+  value := protocol_bdata
+  b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata)))
+  base64.StdEncoding.Encode(b64value, value)
+  b64String := string(b64value)
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  trans.WriteString(JsonQuote(b64String))
+  trans.Flush()
+  s := trans.String()
+  v, e := p.ReadBinary()
+  if e != nil {
+    t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+  }
+  if len(v) != len(value) {
+    t.Fatalf("Bad value for %s value length %v, wrote: %v, received length: %v", thetype, len(value), s, len(v))
+  }
+  for i := 0; i < len(v); i++ {
+    if v[i] != value[i] {
+      t.Fatalf("Bad value for %s at index %d value %v, wrote: %v, received: %v", thetype, i, value[i], s, v[i])
+    }
+  }
+  v1 := new(string)
+  if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String {
+    t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1)
+  }
+  trans.Reset()
+  trans.Close()
+}
+
+func TestWriteJSONProtocolList(t *testing.T) {
+  thetype := "list"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  p.WriteListBegin(TType(DOUBLE), len(DOUBLE_VALUES))
+  for _, value := range DOUBLE_VALUES {
+    if e := p.WriteDouble(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+  }
+  p.WriteListEnd()
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String())
+  }
+  str := trans.String()
+  str1 := new([]interface{})
+  err := json.Unmarshal([]byte(str), str1)
+  if err != nil {
+    t.Fatalf("Unable to decode %s, wrote: %s", thetype, str)
+  }
+  l := *str1
+  if len(l) < 2 {
+    t.Fatalf("List must be at least of length two to include metadata")
+  }
+  if int(l[0].(float64)) != DOUBLE {
+    t.Fatal("Invalid type for list, expected: ", DOUBLE, ", but was: ", l[0])
+  }
+  if int(l[1].(float64)) != len(DOUBLE_VALUES) {
+    t.Fatal("Invalid length for list, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1])
+  }
+  for k, value := range DOUBLE_VALUES {
+    s := l[k+2]
+    if math.IsInf(value, 1) {
+      if s.(string) != JSON_INFINITY {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_INFINITY), str)
+      }
+    } else if math.IsInf(value, 0) {
+      if s.(string) != JSON_NEGATIVE_INFINITY {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY), str)
+      }
+    } else if math.IsNaN(value) {
+      if s.(string) != JSON_NAN {
+        t.Fatalf("Bad value for %s at index %v  %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NAN), str)
+      }
+    } else {
+      if s.(float64) != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s)
+      }
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestWriteJSONProtocolSet(t *testing.T) {
+  thetype := "set"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  p.WriteSetBegin(TType(DOUBLE), len(DOUBLE_VALUES))
+  for _, value := range DOUBLE_VALUES {
+    if e := p.WriteDouble(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+  }
+  p.WriteSetEnd()
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String())
+  }
+  str := trans.String()
+  str1 := new([]interface{})
+  err := json.Unmarshal([]byte(str), str1)
+  if err != nil {
+    t.Fatalf("Unable to decode %s, wrote: %s", thetype, str)
+  }
+  l := *str1
+  if len(l) < 2 {
+    t.Fatalf("Set must be at least of length two to include metadata")
+  }
+  if int(l[0].(float64)) != DOUBLE {
+    t.Fatal("Invalid type for set, expected: ", DOUBLE, ", but was: ", l[0])
+  }
+  if int(l[1].(float64)) != len(DOUBLE_VALUES) {
+    t.Fatal("Invalid length for set, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1])
+  }
+  for k, value := range DOUBLE_VALUES {
+    s := l[k+2]
+    if math.IsInf(value, 1) {
+      if s.(string) != JSON_INFINITY {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_INFINITY), str)
+      }
+    } else if math.IsInf(value, 0) {
+      if s.(string) != JSON_NEGATIVE_INFINITY {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY), str)
+      }
+    } else if math.IsNaN(value) {
+      if s.(string) != JSON_NAN {
+        t.Fatalf("Bad value for %s at index %v  %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NAN), str)
+      }
+    } else {
+      if s.(float64) != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s)
+      }
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestWriteJSONProtocolMap(t *testing.T) {
+  thetype := "map"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  p.WriteMapBegin(TType(I32), TType(DOUBLE), len(DOUBLE_VALUES))
+  for k, value := range DOUBLE_VALUES {
+    if e := p.WriteI32(int32(k)); e != nil {
+      t.Fatalf("Unable to write %s key int32 value %v due to error: %s", thetype, k, e.String())
+    }
+    if e := p.WriteDouble(value); e != nil {
+      t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.String())
+    }
+  }
+  p.WriteMapEnd()
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String())
+  }
+  str := trans.String()
+  if str[0] != '[' || str[len(str)-1] != ']' {
+    t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES)
+  }
+  expectedKeyType, expectedValueType, expectedSize, err := p.ReadMapBegin()
+  if err != nil {
+    t.Fatalf("Error while reading map begin: %s", err.String())
+  }
+  if expectedKeyType != I32 {
+    t.Fatal("Expected map key type ", I32, ", but was ", expectedKeyType)
+  }
+  if expectedValueType != DOUBLE {
+    t.Fatal("Expected map value type ", DOUBLE, ", but was ", expectedValueType)
+  }
+  if expectedSize != len(DOUBLE_VALUES) {
+    t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", expectedSize)
+  }
+  for k, value := range DOUBLE_VALUES {
+    ik, err := p.ReadI32()
+    if err != nil {
+      t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, ik, string(k), err.String())
+    }
+    if int(ik) != k {
+      t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v", thetype, k, ik, k)
+    }
+    dv, err := p.ReadDouble()
+    if err != nil {
+      t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, dv, value, err.String())
+    }
+    s := strconv.Ftoa64(dv, 'g', 10)
+    if math.IsInf(value, 1) {
+      if !math.IsInf(dv, 1) {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_INFINITY))
+      }
+    } else if math.IsInf(value, 0) {
+      if !math.IsInf(dv, 0) {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY))
+      }
+    } else if math.IsNaN(value) {
+      if !math.IsNaN(dv) {
+        t.Fatalf("Bad value for %s at index %v  %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_NAN))
+      }
+    } else {
+      expected := strconv.Ftoa64(value, 'g', 10)
+      if s != expected {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected %v", thetype, k, value, s, expected)
+      }
+      v := float64(0)
+      if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+      }
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+
+func TestReadWriteJSONStruct(t *testing.T) {
+  thetype := "struct"
+  trans := NewTMemoryBuffer()
+  p := NewTJSONProtocol(trans)
+  orig := NewWork()
+  orig.Num1 = 25
+  orig.Num2 = 102
+  orig.Op = ADD
+  orig.Comment = "Add: 25 + 102"
+  if e := orig.Write(p); e != nil {
+    t.Fatalf("Unable to write %s value %#v due to error: %s", thetype, orig, e.String())
+  }
+  p.Flush()
+  t.Log("Memory buffer contents: ", trans.String())
+  expectedString := "{\"1\":{\"i32\":25},\"2\":{\"i32\":102},\"3\":{\"i32\":1},\"4\":{\"str\":\"Add: 25 + 102\"}}"
+  if expectedString != trans.String() {
+    t.Fatalf("Expected JSON Struct with value %#v but have %#v", expectedString, trans.String())
+  }
+  read := NewWork()
+  e := read.Read(p)
+  t.Logf("Read %s value: %#v", thetype, read)
+  if e != nil {
+    t.Fatalf("Unable to read %s due to error: %s", thetype, e.String())
+  }
+  if !orig.Equals(read) {
+    t.Fatalf("Original Write != Read: %#v != %#v ", orig, read)
+  }
+}
+
+func TestReadWriteJSONProtocol(t *testing.T) {
+  ReadWriteProtocolTest(t, NewTJSONProtocolFactory())
+}
diff --git a/lib/go/thrift/tlist.go b/lib/go/thrift/tlist.go
new file mode 100644
index 0000000..778fc3b
--- /dev/null
+++ b/lib/go/thrift/tlist.go
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "container/vector"
+)
+
+/**
+ * Helper class that encapsulates list metadata.
+ *
+ */
+type TList interface {
+  TContainer
+  ElemType() TType
+  At(i int) interface{}
+  Set(i int, data interface{})
+  Push(data interface{})
+  Pop() interface{}
+  Swap(i, j int)
+  Insert(i int, data interface{})
+  Delete(i int)
+  Less(i, j int) bool
+  Iter() <-chan interface{}
+}
+
+type tList struct {
+  elemType TType
+  l        *vector.Vector
+}
+
+func NewTList(t TType, s int) TList {
+  var v vector.Vector
+  return &tList{elemType: t, l: v.Resize(s, s)}
+}
+
+func NewTListDefault() TList {
+  var v vector.Vector
+  return &tList{elemType: TType(STOP), l: &v}
+}
+
+func (p *tList) ElemType() TType {
+  return p.elemType
+}
+
+func (p *tList) Len() int {
+  return p.l.Len()
+}
+
+func (p *tList) At(i int) interface{} {
+  return p.l.At(i)
+}
+
+func (p *tList) Set(i int, data interface{}) {
+  if p.elemType.IsEmptyType() {
+    p.elemType = TypeFromValue(data)
+  }
+  if data, ok := p.elemType.CoerceData(data); ok {
+    p.l.Set(i, data)
+  }
+}
+
+func (p *tList) Push(data interface{}) {
+  if p.elemType.IsEmptyType() {
+    p.elemType = TypeFromValue(data)
+  }
+  data, ok := p.elemType.CoerceData(data)
+  if ok {
+    p.l.Push(data)
+  }
+}
+
+func (p *tList) Pop() interface{} {
+  return p.l.Pop()
+}
+
+func (p *tList) Swap(i, j int) {
+  p.l.Swap(i, j)
+}
+
+func (p *tList) Insert(i int, data interface{}) {
+  p.l.Insert(i, data)
+}
+
+func (p *tList) Delete(i int) {
+  p.l.Delete(i)
+}
+
+func (p *tList) Contains(data interface{}) bool {
+  return p.indexOf(data) >= 0
+}
+
+func (p *tList) Less(i, j int) bool {
+  return p.l.Less(i, j)
+}
+
+func (p *tList) Iter() <-chan interface{} {
+  c := make(chan interface{})
+  go p.iterate(c)
+  return c
+}
+
+func (p *tList) iterate(c chan<- interface{}) {
+  for _, elem := range *p.l {
+    c <- elem
+  }
+  close(c)
+}
+
+func (p *tList) indexOf(data interface{}) int {
+  if data == nil {
+    size := p.l.Len()
+    for i := 0; i < size; i++ {
+      if p.l.At(i) == nil {
+        return i
+      }
+    }
+    return -1
+  }
+  data, ok := p.elemType.CoerceData(data)
+  if data == nil || !ok {
+    return -1
+  }
+  size := p.l.Len()
+  if p.elemType.IsBaseType() || p.elemType.IsEnum() {
+    for i := 0; i < size; i++ {
+      if data == p.l.At(i) {
+        return i
+      }
+    }
+    return -1
+  }
+  if cmp, ok := data.(EqualsOtherInterface); ok {
+    for i := 0; i < size; i++ {
+      if cmp.Equals(p.l.At(i)) {
+        return i
+      }
+    }
+    return -1
+  }
+  switch p.elemType {
+  case MAP:
+    if cmp, ok := data.(EqualsMap); ok {
+      for i := 0; i < size; i++ {
+        v := p.l.At(i)
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TMap)) {
+          return i
+        }
+      }
+      return -1
+    }
+  case SET:
+    if cmp, ok := data.(EqualsSet); ok {
+      for i := 0; i < size; i++ {
+        v := p.l.At(i)
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TSet)) {
+          return i
+        }
+      }
+      return -1
+    }
+  case LIST:
+    if cmp, ok := data.(EqualsList); ok {
+      for i := 0; i < size; i++ {
+        v := p.l.At(i)
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TList)) {
+          return i
+        }
+      }
+      return -1
+    }
+  case STRUCT:
+    if cmp, ok := data.(EqualsStruct); ok {
+      for i := 0; i < size; i++ {
+        v := p.l.At(i)
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TStruct)) {
+          return i
+        }
+      }
+      return -1
+    }
+  }
+  return -1
+}
+
+func (p *tList) Equals(other interface{}) bool {
+  c, cok := p.CompareTo(other)
+  return cok && c == 0
+}
+
+func (p *tList) CompareTo(other interface{}) (int, bool) {
+  return TType(LIST).Compare(p, other)
+}
diff --git a/lib/go/thrift/tmap.go b/lib/go/thrift/tmap.go
new file mode 100644
index 0000000..d042f05
--- /dev/null
+++ b/lib/go/thrift/tmap.go
@@ -0,0 +1,763 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "container/list"
+  "reflect"
+)
+
+/**
+ * Helper class that encapsulates map metadata.
+ *
+ */
+type TMap interface {
+  KeyType() TType
+  ValueType() TType
+  Len() int
+  Set(key, value interface{})
+  Get(key interface{}) (interface{}, bool)
+  Contains(key interface{}) bool
+  Iter() <-chan TMapElem
+  KeyIter() <-chan interface{}
+  ValueIter() <-chan interface{}
+  Keys() []interface{}
+  Values() []interface{}
+  Less(other interface{}) bool
+  Equals(other interface{}) bool
+  CompareTo(other interface{}) (int, bool)
+}
+
+type TMapElem interface {
+  Key() interface{}
+  Value() interface{}
+}
+
+type tMap struct {
+  keyType   TType
+  valueType TType
+  size      int
+  l         *list.List
+  b         map[bool]interface{}
+  i08       map[byte]interface{}
+  i16       map[int16]interface{}
+  i32       map[int32]interface{}
+  i64       map[int64]interface{}
+  f64       map[float64]interface{}
+  s         map[string]interface{}
+}
+
+type tMapElem struct {
+  key   interface{}
+  value interface{}
+}
+
+func (p *tMapElem) Key() interface{} {
+  return p.key
+}
+
+func (p *tMapElem) Value() interface{} {
+  return p.value
+}
+
+func NewTMapElem(k, v interface{}) TMapElem {
+  return &tMapElem{key: k, value: v}
+}
+
+func NewTMap(k, v TType, s int) TMap {
+  return &tMap{keyType: k, valueType: v, size: s, l: list.New()}
+}
+
+func NewTMapDefault() TMap {
+  return NewTMap(STOP, STOP, 0)
+}
+
+func (p *tMap) KeyType() TType {
+  return p.keyType
+}
+
+func (p *tMap) ValueType() TType {
+  return p.valueType
+}
+
+func (p *tMap) Len() int {
+  if p.l.Len() != 0 {
+    return p.l.Len()
+  }
+  switch p.KeyType() {
+  case STOP, VOID:
+    return 0
+  case BOOL:
+    return len(p.b)
+  case BYTE:
+    return len(p.i08)
+  case I16:
+    return len(p.i16)
+  case I32:
+    return len(p.i32)
+  case I64:
+    return len(p.i64)
+  case DOUBLE:
+    return len(p.f64)
+  case STRING, UTF8, UTF16:
+    return len(p.s)
+  default:
+    return p.size
+  }
+  return p.size
+}
+
+func (p *tMap) Get(key interface{}) (interface{}, bool) {
+  if p.KeyType().IsEmptyType() {
+    return nil, false
+  }
+  if key == nil {
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      e := elem.Value.(TMapElem)
+      k := e.Key()
+      if k == nil {
+        return e.Value(), true
+      }
+    }
+    return nil, false
+  }
+  useKey, ok := p.KeyType().CoerceData(key)
+  if !ok {
+    return nil, false
+  }
+  switch p.KeyType() {
+  case STOP, VOID:
+    // if here, then we don't have a key type yet and key is not nil
+    // so this is pretty much an empty map
+    return nil, false
+  case BOOL:
+    m := p.b
+    if m == nil {
+      return nil, false
+    }
+    if v, ok := m[useKey.(bool)]; ok {
+      return v, true
+    }
+    return nil, true
+  case BYTE:
+    m := p.i08
+    if v, ok := m[useKey.(byte)]; ok {
+      return v, true
+    }
+    return nil, false
+  case DOUBLE:
+    m := p.f64
+    if m == nil {
+      return nil, false
+    }
+    if v, ok := m[useKey.(float64)]; ok {
+      return v, true
+    }
+    return nil, false
+  case I16:
+    m := p.i16
+    if m == nil {
+      return nil, false
+    }
+    if v, ok := m[useKey.(int16)]; ok {
+      return v, true
+    }
+    return nil, false
+  case I32:
+    m := p.i32
+    if m == nil {
+      return nil, false
+    }
+    if v, ok := m[useKey.(int32)]; ok {
+      return v, true
+    }
+    return nil, false
+  case I64:
+    m := p.i64
+    if m == nil {
+      return nil, false
+    }
+    if v, ok := m[useKey.(int64)]; ok {
+      return v, true
+    }
+    return nil, false
+  case STRING, UTF8, UTF16:
+    // TODO(pomack) properly handle ENUM
+    m := p.s
+    if m == nil {
+      return nil, false
+    }
+    if v, ok := m[useKey.(string)]; ok {
+      return v, true
+    }
+    return nil, false
+  case STRUCT:
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      e := elem.Value.(TMapElem)
+      k := e.Key()
+      if k == nil {
+        continue
+      }
+      structkey, ok := k.(TStruct)
+      if ok {
+        if structkey.Equals(useKey.(TStruct)) {
+          return e.Value(), true
+        }
+        continue
+      }
+      if reflect.DeepEqual(useKey, k) {
+        return e.Value(), true
+      }
+    }
+    return nil, false
+  case MAP:
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      e := elem.Value.(TMapElem)
+      k := e.Key()
+      if k == nil {
+        continue
+      }
+      mapkey, ok := k.(TMap)
+      if ok {
+        if mapkey.Equals(useKey.(TMap)) {
+          return e.Value(), true
+        }
+        continue
+      }
+      if reflect.DeepEqual(useKey, k) {
+        return e.Value(), true
+      }
+    }
+    return nil, false
+  case SET:
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      e := elem.Value.(TMapElem)
+      k := e.Key()
+      if k == nil {
+        continue
+      }
+      setkey, ok := k.(TSet)
+      if ok {
+        if setkey.Equals(useKey.(TSet)) {
+          return e.Value(), true
+        }
+        continue
+      }
+      if reflect.DeepEqual(useKey, k) {
+        return e.Value(), true
+      }
+    }
+    return nil, false
+  case LIST:
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      e := elem.Value.(TMapElem)
+      k := e.Key()
+      if k == nil {
+        continue
+      }
+      listkey, ok := k.(TList)
+      if ok {
+        if listkey.Equals(useKey.(TList)) {
+          return e.Value(), true
+        }
+        continue
+      }
+      if reflect.DeepEqual(useKey, k) {
+        return e.Value(), true
+      }
+    }
+    return nil, false
+  default:
+    panic("Invalid Thrift element type")
+  }
+  return nil, false
+}
+
+
+func (p *tMap) Set(key, value interface{}) {
+  if p.KeyType() == STOP || p.KeyType() == VOID {
+    p.keyType = TypeFromValue(key)
+  }
+  coercedKey, ok := p.KeyType().CoerceData(key)
+  if !ok {
+    return
+  }
+  if p.ValueType() == STOP || p.ValueType() == VOID {
+    p.valueType = TypeFromValue(value)
+  }
+  coercedValue, ok := p.ValueType().CoerceData(value)
+  if !ok {
+    return
+  }
+  newElem := NewTMapElem(coercedKey, coercedValue)
+  if !p.KeyType().IsBaseType() {
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      k := elem.Value.(TMapElem).Key()
+      if cmp, ok := p.KeyType().Compare(coercedKey, k); ok && cmp >= 0 {
+        if cmp == 0 {
+          p.l.InsertAfter(newElem, elem)
+          p.l.Remove(elem)
+          return
+        }
+        p.l.InsertBefore(newElem, elem)
+        return
+      }
+    }
+    p.l.PushBack(newElem)
+    return
+  }
+  if key == nil {
+    return
+  }
+  switch p.KeyType() {
+  case STOP, VOID:
+    // if here, then we don't have a key type yet and key is not nil
+    // so this is pretty much an empty map
+    return
+  case BOOL:
+    if p.b == nil {
+      p.b = make(map[bool]interface{})
+    }
+    b := coercedKey.(bool)
+    p.b[b] = value
+  case BYTE:
+    if p.i08 == nil {
+      p.i08 = make(map[byte]interface{})
+    }
+    b := coercedKey.(byte)
+    p.i08[b] = value
+  case DOUBLE:
+    if p.f64 == nil {
+      p.f64 = make(map[float64]interface{})
+    }
+    b := coercedKey.(float64)
+    p.f64[b] = value
+  case I16:
+    if p.i16 == nil {
+      p.i16 = make(map[int16]interface{})
+    }
+    b := coercedKey.(int16)
+    p.i16[b] = value
+  case I32:
+    if p.i32 == nil {
+      p.i32 = make(map[int32]interface{})
+    }
+    b := coercedKey.(int32)
+    p.i32[b] = value
+  case I64:
+    if p.i64 == nil {
+      p.i64 = make(map[int64]interface{})
+    }
+    b := coercedKey.(int64)
+    p.i64[b] = value
+  case STRING, UTF8, UTF16:
+    if p.s == nil {
+      p.s = make(map[string]interface{})
+    }
+    b := coercedKey.(string)
+    p.s[b] = value
+  case STRUCT, MAP, SET, LIST:
+    panic("Should never be here")
+  default:
+    panic("Should never be here")
+  }
+}
+
+func (p *tMap) Contains(key interface{}) bool {
+  coercedKey, ok := p.KeyType().CoerceData(key)
+  if !ok {
+    return false
+  }
+  if coercedKey == nil {
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      k := elem.Value.(TMapElem).Key()
+      if k == nil {
+        return true
+      }
+    }
+    return false
+  }
+  if !ok {
+    return false
+  }
+  switch p.KeyType() {
+  case STOP:
+    // if here, then we don't have a key type yet and key is not nil
+    // so this is pretty much an empty map
+    return false
+  case VOID:
+    // if here, then we don't have a key type yet and key is not nil
+    // so this is pretty much an empty map
+    return false
+  case BOOL:
+    m := p.b
+    if m == nil {
+      return false
+    }
+    _, ok := m[coercedKey.(bool)]
+    return ok
+  case BYTE:
+    m := p.i08
+    _, ok := m[coercedKey.(byte)]
+    return ok
+  case DOUBLE:
+    m := p.f64
+    if m == nil {
+      return false
+    }
+    _, ok := m[coercedKey.(float64)]
+    return ok
+  case I16:
+    m := p.i16
+    if m == nil {
+      return false
+    }
+    _, ok := m[coercedKey.(int16)]
+    return ok
+  case I32:
+    m := p.i32
+    if m == nil {
+      return false
+    }
+    _, ok := m[coercedKey.(int32)]
+    return ok
+  case I64:
+    m := p.i64
+    if m == nil {
+      return false
+    }
+    _, ok := m[coercedKey.(int64)]
+    return ok
+  case STRING, UTF8, UTF16:
+    // TODO(pomack) properly handle ENUM
+    m := p.s
+    if m == nil {
+      return false
+    }
+    _, ok := m[coercedKey.(string)]
+    return ok
+  case STRUCT:
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      e := elem.Value.(TMapElem)
+      k := e.Key()
+      if k == nil {
+        continue
+      }
+      structkey, ok := k.(TStruct)
+      if ok {
+        if structkey.Equals(coercedKey.(TStruct)) {
+          return true
+        }
+        continue
+      }
+      if reflect.DeepEqual(coercedKey, k) {
+        return true
+      }
+    }
+    return false
+  case MAP:
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      e := elem.Value.(TMapElem)
+      k := e.Key()
+      if k == nil {
+        continue
+      }
+      mapkey, ok := k.(TMap)
+      if ok {
+        if mapkey.Equals(coercedKey.(TMap)) {
+          return true
+        }
+        continue
+      }
+    }
+    return false
+  case SET:
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      e := elem.Value.(TMapElem)
+      k := e.Key()
+      if k == nil {
+        continue
+      }
+      setkey, ok := k.(TSet)
+      if ok {
+        if setkey.Equals(coercedKey.(TSet)) {
+          return true
+        }
+        continue
+      }
+    }
+    return false
+  case LIST:
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      e := elem.Value.(TMapElem)
+      k := e.Key()
+      if k == nil {
+        continue
+      }
+      listkey, ok := k.(TList)
+      if ok {
+        if listkey.Equals(coercedKey.(TList)) {
+          return true
+        }
+        continue
+      }
+    }
+    return false
+  default:
+    panic("Invalid Thrift element type")
+  }
+  return false
+}
+
+// Iterate over all elements; driver for range
+func (p *tMap) iterate(c chan<- TMapElem) {
+  switch p.KeyType() {
+  case STOP, VOID:
+    close(c)
+  case BOOL:
+    for k, v := range p.b {
+      c <- NewTMapElem(k, v)
+    }
+    close(c)
+  case BYTE:
+    for k, v := range p.i08 {
+      c <- NewTMapElem(k, v)
+    }
+    close(c)
+  case I16:
+    for k, v := range p.i16 {
+      c <- NewTMapElem(k, v)
+    }
+    close(c)
+  case I32:
+    for k, v := range p.i32 {
+      c <- NewTMapElem(k, v)
+    }
+    close(c)
+  case I64:
+    for k, v := range p.i64 {
+      c <- NewTMapElem(k, v)
+    }
+    close(c)
+  case DOUBLE:
+    for k, v := range p.f64 {
+      c <- NewTMapElem(k, v)
+    }
+    close(c)
+  case STRING, UTF8, UTF16:
+    for k, v := range p.s {
+      c <- NewTMapElem(k, v)
+    }
+    close(c)
+  case STRUCT:
+    for v := p.l.Front(); v != nil; v = v.Next() {
+      c <- v.Value.(TMapElem)
+    }
+    close(c)
+  case LIST:
+    for v := p.l.Front(); v != nil; v = v.Next() {
+      c <- v.Value.(TMapElem)
+    }
+    close(c)
+  case SET:
+    for v := p.l.Front(); v != nil; v = v.Next() {
+      c <- v.Value.(TMapElem)
+    }
+    close(c)
+  default:
+    panic("Invalid Thrift type")
+  }
+}
+
+// Channel iterator for range.
+func (p *tMap) Iter() <-chan TMapElem {
+  c := make(chan TMapElem)
+  go p.iterate(c)
+  return c
+}
+
+// Iterate over all keys; driver for range
+func (p *tMap) iterateKeys(c chan<- interface{}) {
+  switch p.KeyType() {
+  case STOP, VOID:
+    close(c)
+  case BOOL:
+    for k, _ := range p.b {
+      c <- k
+    }
+    close(c)
+  case BYTE:
+    for k, _ := range p.i08 {
+      c <- k
+    }
+    close(c)
+  case I16:
+    for k, _ := range p.i16 {
+      c <- k
+    }
+    close(c)
+  case I32:
+    for k, _ := range p.i32 {
+      c <- k
+    }
+    close(c)
+  case I64:
+    for k, _ := range p.i64 {
+      c <- k
+    }
+    close(c)
+  case DOUBLE:
+    for k, _ := range p.f64 {
+      c <- k
+    }
+    close(c)
+  case STRING, UTF8, UTF16:
+    for k, _ := range p.s {
+      c <- k
+    }
+    close(c)
+  case STRUCT:
+    for v := p.l.Front(); v != nil; v = v.Next() {
+      c <- v.Value.(TMapElem).Key()
+    }
+    close(c)
+  case LIST:
+    for v := p.l.Front(); v != nil; v = v.Next() {
+      c <- v.Value.(TMapElem).Key()
+    }
+    close(c)
+  case SET:
+    for v := p.l.Front(); v != nil; v = v.Next() {
+      c <- v.Value.(TMapElem).Key()
+    }
+    close(c)
+  default:
+    panic("Invalid Thrift type")
+  }
+}
+
+func (p *tMap) KeyIter() <-chan interface{} {
+  c := make(chan interface{})
+  go p.iterateKeys(c)
+  return c
+}
+
+// Iterate over all values; driver for range
+func (p *tMap) iterateValues(c chan<- interface{}) {
+  switch p.KeyType() {
+  case STOP, VOID:
+    close(c)
+  case BOOL:
+    for _, v := range p.b {
+      c <- v
+    }
+    close(c)
+  case BYTE:
+    for _, v := range p.i08 {
+      c <- v
+    }
+    close(c)
+  case I16:
+    for _, v := range p.i16 {
+      c <- v
+    }
+    close(c)
+  case I32:
+    for _, v := range p.i32 {
+      c <- v
+    }
+    close(c)
+  case I64:
+    for _, v := range p.i64 {
+      c <- v
+    }
+    close(c)
+  case DOUBLE:
+    for _, v := range p.f64 {
+      c <- v
+    }
+    close(c)
+  case STRING, UTF8, UTF16:
+    for _, v := range p.s {
+      c <- v
+    }
+    close(c)
+  case STRUCT:
+    for v := p.l.Front(); v != nil; v = v.Next() {
+      c <- v.Value.(TMapElem).Value()
+    }
+    close(c)
+  case LIST:
+    for v := p.l.Front(); v != nil; v = v.Next() {
+      c <- v.Value.(TMapElem).Value()
+    }
+    close(c)
+  case SET:
+    for v := p.l.Front(); v != nil; v = v.Next() {
+      c <- v.Value.(TMapElem).Value()
+    }
+    close(c)
+  default:
+    panic("Invalid Thrift type")
+  }
+}
+
+func (p *tMap) ValueIter() <-chan interface{} {
+  c := make(chan interface{})
+  go p.iterateValues(c)
+  return c
+}
+
+
+func (p *tMap) Less(other interface{}) bool {
+  cmp, ok := p.CompareTo(other)
+  return ok && cmp > 0
+}
+
+func (p *tMap) Equals(other interface{}) bool {
+  c, cok := p.CompareTo(other)
+  return cok && c == 0
+}
+
+func (p *tMap) CompareTo(other interface{}) (int, bool) {
+  return TType(MAP).Compare(p, other)
+}
+
+func (p *tMap) Keys() []interface{} {
+  size := p.Len()
+  values := make([]interface{}, size, size)
+  i := 0
+  for k := range p.KeyIter() {
+    values[i] = k
+    i++
+  }
+  return values
+}
+
+func (p *tMap) Values() []interface{} {
+  size := p.Len()
+  values := make([]interface{}, size, size)
+  i := 0
+  for v := range p.ValueIter() {
+    values[i] = v
+    i++
+  }
+  return values
+}
diff --git a/lib/go/thrift/tmemory_buffer.go b/lib/go/thrift/tmemory_buffer.go
new file mode 100644
index 0000000..69b794e
--- /dev/null
+++ b/lib/go/thrift/tmemory_buffer.go
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "bytes"
+  "io"
+  "os"
+)
+
+/**
+ * Memory buffer-based implementation of the TTransport interface.
+ *
+ */
+type TMemoryBuffer struct {
+  buf  *bytes.Buffer
+  size int
+}
+
+type TMemoryBufferTransportFactory struct {
+  size int
+}
+
+func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) TTransport {
+  if trans != nil {
+    t, ok := trans.(*TMemoryBuffer)
+    if ok && t.size > 0 {
+      return NewTMemoryBufferLen(t.size)
+    }
+  }
+  return NewTMemoryBufferLen(p.size)
+}
+
+func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory {
+  return &TMemoryBufferTransportFactory{size: size}
+}
+
+func NewTMemoryBuffer() *TMemoryBuffer {
+  return &TMemoryBuffer{buf: &bytes.Buffer{}, size: 0}
+}
+
+func NewTMemoryBufferLen(size int) *TMemoryBuffer {
+  buf := make([]byte, 0, size)
+  return &TMemoryBuffer{buf: bytes.NewBuffer(buf), size: size}
+}
+
+func (p *TMemoryBuffer) IsOpen() bool {
+  return true
+}
+
+func (p *TMemoryBuffer) Open() os.Error {
+  return nil
+}
+
+func (p *TMemoryBuffer) Peek() bool {
+  return p.IsOpen()
+}
+
+func (p *TMemoryBuffer) Close() os.Error {
+  p.buf.Reset()
+  return nil
+}
+
+func (p *TMemoryBuffer) Read(buf []byte) (int, os.Error) {
+  return p.buf.Read(buf)
+}
+
+func (p *TMemoryBuffer) ReadAll(buf []byte) (int, os.Error) {
+  return ReadAllTransport(p, buf)
+}
+
+func (p *TMemoryBuffer) ReadByte() (byte, os.Error) {
+  return p.buf.ReadByte()
+}
+
+func (p *TMemoryBuffer) ReadFrom(r io.Reader) (int64, os.Error) {
+  return p.buf.ReadFrom(r)
+}
+
+func (p *TMemoryBuffer) Write(buf []byte) (int, os.Error) {
+  return p.buf.Write(buf)
+}
+
+func (p *TMemoryBuffer) WriteString(buf string) (int, os.Error) {
+  return p.buf.WriteString(buf)
+}
+
+func (p *TMemoryBuffer) WriteTo(w io.Writer) (int64, os.Error) {
+  return p.buf.WriteTo(w)
+}
+
+func (p *TMemoryBuffer) Flush() os.Error {
+  return nil
+}
+
+func (p *TMemoryBuffer) Reset() {
+  p.buf.Reset()
+}
+
+func (p *TMemoryBuffer) Bytes() []byte {
+  return p.buf.Bytes()
+}
+
+func (p *TMemoryBuffer) Len() int {
+  return p.buf.Len()
+}
+
+func (p *TMemoryBuffer) String() string {
+  return p.buf.String()
+}
diff --git a/lib/go/thrift/tmemory_buffer_test.go b/lib/go/thrift/tmemory_buffer_test.go
new file mode 100644
index 0000000..5d17864
--- /dev/null
+++ b/lib/go/thrift/tmemory_buffer_test.go
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+)
+
+func TestMemoryBuffer(t *testing.T) {
+  trans := NewTMemoryBufferLen(1024)
+  TransportTest(t, trans, trans)
+}
diff --git a/lib/go/thrift/tmessage.go b/lib/go/thrift/tmessage.go
new file mode 100644
index 0000000..c768cb4
--- /dev/null
+++ b/lib/go/thrift/tmessage.go
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+/**
+ * Helper class that encapsulates struct metadata.
+ *
+ */
+type TMessage interface {
+  Name() string
+  TypeId() TMessageType
+  SeqId() int
+  Equals(other TMessage) bool
+}
+type tMessage struct {
+  name   string
+  typeId TMessageType
+  seqid  int
+}
+
+func NewTMessageDefault() TMessage {
+  return NewTMessage("", STOP, 0)
+}
+
+func NewTMessage(n string, t TMessageType, s int) TMessage {
+  return &tMessage{name: n, typeId: t, seqid: s}
+}
+
+func (p *tMessage) Name() string {
+  return p.name
+}
+
+func (p *tMessage) TypeId() TMessageType {
+  return p.typeId
+}
+
+func (p *tMessage) SeqId() int {
+  return p.seqid
+}
+
+func (p *tMessage) String() string {
+  return "<TMessage name:'" + p.name + "' type: " + string(p.typeId) + " seqid:" + string(p.seqid) + ">"
+}
+
+func (p *tMessage) Equals(other TMessage) bool {
+  return p.name == other.Name() && p.typeId == other.TypeId() && p.seqid == other.SeqId()
+}
+
+var EMPTY_MESSAGE TMessage
+
+func init() {
+  EMPTY_MESSAGE = NewTMessageDefault()
+}
diff --git a/lib/go/thrift/tmessagetype.go b/lib/go/thrift/tmessagetype.go
new file mode 100644
index 0000000..b31c66c
--- /dev/null
+++ b/lib/go/thrift/tmessagetype.go
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+/**
+ * Message type constants in the Thrift protocol.
+ *
+ */
+type TMessageType int32
+
+const (
+  INVALID_TMESSAGE_TYPE TMessageType = 0
+  CALL                  TMessageType = 1
+  REPLY                 TMessageType = 2
+  EXCEPTION             TMessageType = 3
+  ONEWAY                TMessageType = 4
+)
diff --git a/lib/go/thrift/tnonblocking_server.go b/lib/go/thrift/tnonblocking_server.go
new file mode 100644
index 0000000..e234c5a
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_server.go
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "os"
+)
+
+/**
+ * A nonblocking TServer implementation. This allows for fairness amongst all
+ * connected clients in terms of invocations.
+ *
+ * This server is inherently single-threaded. If you want a limited thread pool
+ * coupled with invocation-fairness, see THsHaServer.
+ *
+ * To use this server, you MUST use a TFramedTransport at the outermost
+ * transport, otherwise this server will be unable to determine when a whole
+ * method call has been read off the wire. Clients must also use TFramedTransport.
+ */
+type TNonblockingServer struct {
+  /** Flag for stopping the server */
+  stopped bool
+
+  processorFactory       TProcessorFactory
+  serverTransport        TServerTransport
+  inputTransportFactory  TTransportFactory
+  outputTransportFactory TTransportFactory
+  inputProtocolFactory   TProtocolFactory
+  outputProtocolFactory  TProtocolFactory
+}
+
+
+func NewTNonblockingServer2(processor TProcessor, serverTransport TServerTransport) *TNonblockingServer {
+  return NewTNonblockingServerFactory2(NewTProcessorFactory(processor), serverTransport)
+}
+
+func NewTNonblockingServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TNonblockingServer {
+  return NewTNonblockingServerFactory4(NewTProcessorFactory(processor),
+    serverTransport,
+    transportFactory,
+    protocolFactory,
+  )
+}
+
+func NewTNonblockingServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TNonblockingServer {
+  return NewTNonblockingServerFactory6(NewTProcessorFactory(processor),
+    serverTransport,
+    inputTransportFactory,
+    outputTransportFactory,
+    inputProtocolFactory,
+    outputProtocolFactory,
+  )
+}
+
+func NewTNonblockingServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TNonblockingServer {
+  return NewTNonblockingServerFactory6(processorFactory,
+    serverTransport,
+    NewTTransportFactory(),
+    NewTTransportFactory(),
+    NewTBinaryProtocolFactoryDefault(),
+    NewTBinaryProtocolFactoryDefault(),
+  )
+}
+
+func NewTNonblockingServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TNonblockingServer {
+  return NewTNonblockingServerFactory6(processorFactory,
+    serverTransport,
+    transportFactory,
+    transportFactory,
+    protocolFactory,
+    protocolFactory,
+  )
+}
+
+func NewTNonblockingServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TNonblockingServer {
+  return &TNonblockingServer{processorFactory: processorFactory,
+    serverTransport:        serverTransport,
+    inputTransportFactory:  inputTransportFactory,
+    outputTransportFactory: outputTransportFactory,
+    inputProtocolFactory:   inputProtocolFactory,
+    outputProtocolFactory:  outputProtocolFactory,
+  }
+}
+
+func (p *TNonblockingServer) ProcessorFactory() TProcessorFactory {
+  return p.processorFactory
+}
+
+func (p *TNonblockingServer) ServerTransport() TServerTransport {
+  return p.serverTransport
+}
+
+func (p *TNonblockingServer) InputTransportFactory() TTransportFactory {
+  return p.inputTransportFactory
+}
+
+func (p *TNonblockingServer) OutputTransportFactory() TTransportFactory {
+  return p.outputTransportFactory
+}
+
+func (p *TNonblockingServer) InputProtocolFactory() TProtocolFactory {
+  return p.inputProtocolFactory
+}
+
+func (p *TNonblockingServer) OutputProtocolFactory() TProtocolFactory {
+  return p.outputProtocolFactory
+}
+
+func (p *TNonblockingServer) Serve() os.Error {
+  p.stopped = false
+  err := p.serverTransport.Listen()
+  if err != nil {
+    return err
+  }
+  for !p.stopped {
+    client, err := p.serverTransport.Accept()
+    if err != nil {
+      return err
+    }
+    if client != nil {
+      go p.processRequest(client)
+    }
+  }
+  return nil
+}
+
+func (p *TNonblockingServer) Stop() os.Error {
+  p.stopped = true
+  p.serverTransport.Interrupt()
+  return nil
+}
+
+func (p *TNonblockingServer) IsStopped() bool {
+  return p.stopped
+}
+
+func (p *TNonblockingServer) processRequest(client TTransport) {
+  processor := p.processorFactory.GetProcessor(client)
+  inputTransport := p.inputTransportFactory.GetTransport(client)
+  outputTransport := p.outputTransportFactory.GetTransport(client)
+  inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport)
+  outputProtocol := p.outputProtocolFactory.GetProtocol(outputTransport)
+  if inputTransport != nil {
+    defer inputTransport.Close()
+  }
+  if outputTransport != nil {
+    defer outputTransport.Close()
+  }
+  for {
+    ok, e := processor.Process(inputProtocol, outputProtocol)
+    if e != nil {
+      if !p.stopped {
+        // TODO(pomack) log error
+        break
+      }
+    }
+    if !ok {
+      break
+    }
+  }
+}
diff --git a/lib/go/thrift/tnonblocking_server_socket.go b/lib/go/thrift/tnonblocking_server_socket.go
new file mode 100644
index 0000000..3c9dbaa
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_server_socket.go
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "net"
+  "os"
+)
+
+/**
+ * Socket implementation of the TTransport interface. To be commented soon!
+ */
+type TNonblockingServerSocket struct {
+  listener net.Listener
+  addr     net.Addr
+  /**
+   * Socket timeout
+   */
+  nsecTimeout int64
+}
+
+type TNonblockingServerSocketTransportFactory struct {
+  addr net.Addr
+}
+
+func (p *TNonblockingServerSocketTransportFactory) GetTransport(trans TTransport) TTransport {
+  if trans != nil {
+    t, ok := trans.(*TNonblockingServerSocket)
+    if ok && t.addr != nil {
+      s, _ := NewTNonblockingServerSocketAddr(t.addr)
+      s.SetTimeout(t.nsecTimeout)
+      return s
+    }
+  }
+  s, _ := NewTNonblockingServerSocketAddr(p.addr)
+  return s
+}
+
+func NewTNonblockingServerSocketTransportFactory(addr net.Addr) *TNonblockingServerSocketTransportFactory {
+  return &TNonblockingServerSocketTransportFactory{addr: addr}
+}
+
+
+func NewTNonblockingServerSocketListener(listener net.Listener) (*TNonblockingServerSocket, TTransportException) {
+  s := &TNonblockingServerSocket{listener: listener, addr: listener.Addr()}
+  return s, nil
+}
+
+func NewTNonblockingServerSocketAddr(addr net.Addr) (*TNonblockingServerSocket, TTransportException) {
+  s := &TNonblockingServerSocket{addr: addr}
+  return s, nil
+}
+
+func (p *TNonblockingServerSocket) Listen() os.Error {
+  return p.Open()
+}
+
+/**
+ * Sets the socket timeout
+ *
+ * @param timeout Nanoseconds timeout
+ */
+func (p *TNonblockingServerSocket) SetTimeout(nsecTimeout int64) os.Error {
+  p.nsecTimeout = nsecTimeout
+  return nil
+}
+
+/**
+ * Checks whether the socket is connected.
+ */
+func (p *TNonblockingServerSocket) IsOpen() bool {
+  return p.listener != nil
+}
+
+/**
+ * Connects the socket, creating a new socket object if necessary.
+ */
+func (p *TNonblockingServerSocket) Open() os.Error {
+  if !p.IsOpen() {
+    l, err := net.Listen(p.addr.Network(), p.addr.String())
+    if err != nil {
+      return err
+    }
+    p.listener = l
+    return nil
+  }
+  return NewTTransportException(ALREADY_OPEN, "Server socket already open")
+}
+
+/**
+ * Perform a nonblocking read into buffer.
+ */
+func (p *TNonblockingServerSocket) Read(buf []byte) (int, os.Error) {
+  return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TNonblockingServerSocket.Read([]byte) is not implemented")
+}
+
+func (p *TNonblockingServerSocket) ReadAll(buf []byte) (int, os.Error) {
+  return ReadAllTransport(p, buf)
+}
+
+/**
+ * Perform a nonblocking write of the data in buffer;
+ */
+func (p *TNonblockingServerSocket) Write(buf []byte) (int, os.Error) {
+  return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TNonblockingServerSocket.Write([]byte) is not implemented")
+}
+
+/**
+ * Flushes the underlying output stream if not null.
+ */
+func (p *TNonblockingServerSocket) Flush() os.Error {
+  return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TNonblockingServerSocket.Flush() is not implemented")
+}
+
+func (p *TNonblockingServerSocket) Addr() net.Addr {
+  return p.addr
+}
+
+func (p *TNonblockingServerSocket) Accept() (TTransport, os.Error) {
+  if !p.IsOpen() {
+    return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
+  }
+  conn, err := p.listener.Accept()
+  if err != nil {
+    return nil, NewTTransportExceptionFromOsError(err)
+  }
+  conn.SetTimeout(p.nsecTimeout)
+  return NewTSocketConn(conn)
+}
+
+func (p *TNonblockingServerSocket) Peek() bool {
+  return p.IsOpen()
+}
+
+/**
+ * Closes the socket.
+ */
+func (p *TNonblockingServerSocket) Close() (err os.Error) {
+  if p.IsOpen() {
+    err := p.listener.Close()
+    if err != nil {
+      return NewTTransportExceptionFromOsError(err)
+    }
+    p.listener = nil
+  }
+  return nil
+}
+
+func (p *TNonblockingServerSocket) Interrupt() os.Error {
+  // probably not right
+  return p.Close()
+}
diff --git a/lib/go/thrift/tnonblocking_socket.go b/lib/go/thrift/tnonblocking_socket.go
new file mode 100644
index 0000000..a1c0310
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_socket.go
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "net"
+  "os"
+)
+
+/**
+ * Socket implementation of the TTransport interface. To be commented soon!
+ */
+type TNonblockingSocket struct {
+  conn net.Conn
+  addr net.Addr
+  /**
+   * Socket timeout
+   */
+  nsecTimeout int64
+}
+
+type TNonblockingSocketTransportFactory struct {
+  addr net.Addr
+}
+
+func (p *TNonblockingSocketTransportFactory) GetTransport(trans TTransport) TTransport {
+  if trans != nil {
+    t, ok := trans.(*TNonblockingSocket)
+    if ok {
+      s, _ := NewTNonblockingSocketAddr(t.addr)
+      s.SetTimeout(t.nsecTimeout)
+      return s
+    }
+  }
+  s, _ := NewTNonblockingSocketAddr(p.addr)
+  return s
+}
+
+func NewTNonblockingSocketTransportFactory(addr net.Addr) *TNonblockingSocketTransportFactory {
+  return &TNonblockingSocketTransportFactory{addr: addr}
+}
+
+func NewTNonblockingSocketConn(conn net.Conn) (*TNonblockingSocket, TTransportException) {
+  s := &TNonblockingSocket{conn: conn, addr: conn.RemoteAddr()}
+  return s, nil
+}
+
+func NewTNonblockingSocketAddr(addr net.Addr) (*TNonblockingSocket, TTransportException) {
+  s := &TNonblockingSocket{addr: addr}
+  return s, nil
+}
+
+/**
+ * Sets the socket timeout
+ *
+ * @param nsecTimeout Nanoseconds timeout
+ */
+func (p *TNonblockingSocket) SetTimeout(nsecTimeout int64) os.Error {
+  p.nsecTimeout = nsecTimeout
+  if p.IsOpen() {
+    if err := p.conn.SetTimeout(nsecTimeout); err != nil {
+      LOGGER.Print("Could not set socket timeout.", err)
+      return err
+    }
+  }
+  return nil
+}
+
+/**
+ * Checks whether the socket is connected.
+ */
+func (p *TNonblockingSocket) IsOpen() bool {
+  return p.conn != nil
+}
+
+/**
+ * Connects the socket, creating a new socket object if necessary.
+ */
+func (p *TNonblockingSocket) Open() os.Error {
+  if p.IsOpen() {
+    return NewTTransportException(ALREADY_OPEN, "Socket already connected.")
+  }
+  if p.addr == nil {
+    return NewTTransportException(NOT_OPEN, "Cannot open nil address.")
+  }
+  if len(p.addr.Network()) == 0 {
+    return NewTTransportException(NOT_OPEN, "Cannot open bad network name.")
+  }
+  if len(p.addr.String()) == 0 {
+    return NewTTransportException(NOT_OPEN, "Cannot open bad address.")
+  }
+
+  var err os.Error
+  if p.conn, err = net.Dial(p.addr.Network(), "", p.addr.String()); err != nil {
+    LOGGER.Print("Could not open socket", err.String())
+    return NewTTransportException(NOT_OPEN, err.String())
+  }
+  if p.conn != nil {
+    p.conn.SetTimeout(p.nsecTimeout)
+  }
+  return nil
+}
+
+/**
+ * Perform a nonblocking read into buffer.
+ */
+func (p *TNonblockingSocket) Read(buf []byte) (int, os.Error) {
+  if !p.IsOpen() {
+    return 0, NewTTransportException(NOT_OPEN, "Connection not open")
+  }
+  n, err := p.conn.Read(buf)
+  return n, NewTTransportExceptionFromOsError(err)
+}
+
+
+func (p *TNonblockingSocket) ReadAll(buf []byte) (int, os.Error) {
+  return ReadAllTransport(p, buf)
+}
+
+/**
+ * Perform a nonblocking write of the data in buffer;
+ */
+func (p *TNonblockingSocket) Write(buf []byte) (int, os.Error) {
+  if !p.IsOpen() {
+    return 0, NewTTransportException(NOT_OPEN, "Connection not open")
+  }
+  return p.conn.Write(buf)
+}
+
+/**
+ * Flushes the underlying output stream if not null.
+ */
+func (p *TNonblockingSocket) Flush() os.Error {
+  if !p.IsOpen() {
+    return NewTTransportException(NOT_OPEN, "Connection not open")
+  }
+  f, ok := p.conn.(Flusher)
+  if ok {
+    err := f.Flush()
+    if err != nil {
+      return NewTTransportExceptionFromOsError(err)
+    }
+  }
+  return nil
+}
+
+func (p *TNonblockingSocket) Addr() net.Addr {
+  return p.addr
+}
+
+func (p *TNonblockingSocket) Peek() bool {
+  return p.IsOpen()
+}
+
+/**
+ * Closes the socket.
+ */
+func (p *TNonblockingSocket) Close() os.Error {
+  if p.conn != nil {
+    if err := p.conn.Close(); err != nil {
+      LOGGER.Print("Could not close socket.", err.String())
+      return err
+    }
+    p.conn = nil
+  }
+  return nil
+}
+
+func (p *TNonblockingSocket) Interrupt() os.Error {
+  if !p.IsOpen() {
+    return nil
+  }
+  // TODO(pomack) fix Interrupt as it is probably not right
+  return p.Close()
+}
diff --git a/lib/go/thrift/tnonblocking_transport.go b/lib/go/thrift/tnonblocking_transport.go
new file mode 100644
index 0000000..da9c26d
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_transport.go
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+type TNonblockingTransport interface {
+  TTransport
+}
diff --git a/lib/go/thrift/tnonblocking_transport_test.go b/lib/go/thrift/tnonblocking_transport_test.go
new file mode 100644
index 0000000..7d019db
--- /dev/null
+++ b/lib/go/thrift/tnonblocking_transport_test.go
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+  "net"
+)
+
+func TestNonblockingTransportServerToClient(t *testing.T) {
+
+  addr, err := FindAvailableTCPServerPort(40000)
+  if err != nil {
+    t.Fatalf("Unable to find available tcp port addr: %s", err)
+  }
+  trans1, err := NewTNonblockingServerSocketAddr(addr)
+  if err != nil {
+    t.Fatalf("Unable to setup server socket listener: %s", err)
+  }
+  trans1.Open()
+  trans2, err := NewTNonblockingSocketAddr(addr)
+  if err != nil {
+    t.Fatalf("Unable to setup client socket: %s", err)
+  }
+  trans1.SetTimeout(10)
+  trans2.SetTimeout(10)
+  err = trans2.Open()
+  if err != nil {
+    t.Fatalf("Unable to connect client to server: %s", err)
+  }
+  s, err := trans1.Accept()
+  if err != nil {
+    t.Fatalf("Unable to accept client connection from server: %s", err)
+  }
+  //s.SetTimeout(10)
+  TransportTest(t, NewTFramedTransport(s), NewTFramedTransport(trans2))
+  trans1.Close()
+}
+
+func TestNonblockingTransportClientToServer(t *testing.T) {
+  addr, err := FindAvailableTCPServerPort(40000)
+  if err != nil {
+    t.Fatalf("Unable to find available tcp port addr: %s", err)
+  }
+  l, err := net.Listen(addr.Network(), addr.String())
+  if err != nil {
+    t.Fatalf("Unable to setup listener: %s", err)
+  }
+  trans1, err := NewTNonblockingServerSocketListener(l)
+  if err != nil {
+    t.Fatalf("Unable to setup server socket listener: %s", err)
+  }
+  trans2, err := NewTNonblockingSocketAddr(l.Addr())
+  if err != nil {
+    t.Fatalf("Unable to setup client socket: %s", err)
+  }
+  trans1.SetTimeout(10)
+  trans2.SetTimeout(10)
+  err = trans2.Open()
+  if err != nil {
+    t.Fatalf("Unable to connect client to server: %s", err)
+  }
+  s, err := trans1.Accept()
+  if err != nil {
+    t.Fatalf("Unable to accept client connection from server: %s", err)
+  }
+  //s.SetTimeout(10)
+  TransportTest(t, NewTFramedTransport(trans2), NewTFramedTransport(s))
+  trans1.Close()
+}
diff --git a/lib/go/thrift/tnumeric.go b/lib/go/thrift/tnumeric.go
new file mode 100644
index 0000000..b1f6508
--- /dev/null
+++ b/lib/go/thrift/tnumeric.go
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package thrift
+
+import (
+  "math"
+  "strconv"
+)
+
+type Numeric interface {
+  Int64() int64
+  Int32() int32
+  Int16() int16
+  Byte() byte
+  Int() int
+  Float64() float64
+  Float32() float32
+  String() string
+  isNull() bool
+}
+
+type numeric struct {
+  iValue int64
+  dValue float64
+  sValue string
+  isNil  bool
+}
+
+var (
+  INFINITY          Numeric
+  NEGATIVE_INFINITY Numeric
+  NAN               Numeric
+  ZERO              Numeric
+  NUMERIC_NULL      Numeric
+)
+
+func NewNumericFromDouble(dValue float64) Numeric {
+  if math.IsInf(dValue, 1) {
+    return INFINITY
+  }
+  if math.IsInf(dValue, -1) {
+    return NEGATIVE_INFINITY
+  }
+  if math.IsNaN(dValue) {
+    return NAN
+  }
+  iValue := int64(dValue)
+  sValue := strconv.Ftoa64(dValue, 'g', 10)
+  isNil := false
+  return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromI64(iValue int64) Numeric {
+  dValue := float64(iValue)
+  sValue := string(iValue)
+  isNil := false
+  return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromI32(iValue int32) Numeric {
+  dValue := float64(iValue)
+  sValue := string(iValue)
+  isNil := false
+  return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromString(sValue string) Numeric {
+  if sValue == INFINITY.String() {
+    return INFINITY
+  }
+  if sValue == NEGATIVE_INFINITY.String() {
+    return NEGATIVE_INFINITY
+  }
+  if sValue == NAN.String() {
+    return NAN
+  }
+  iValue, _ := strconv.Atoi64(sValue)
+  dValue, _ := strconv.Atof64(sValue)
+  isNil := len(sValue) == 0
+  return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
+}
+
+func NewNumericFromJSONString(sValue string, isNull bool) Numeric {
+  if isNull {
+    return NewNullNumeric()
+  }
+  if sValue == JSON_INFINITY {
+    return INFINITY
+  }
+  if sValue == JSON_NEGATIVE_INFINITY {
+    return NEGATIVE_INFINITY
+  }
+  if sValue == JSON_NAN {
+    return NAN
+  }
+  iValue, _ := strconv.Atoi64(sValue)
+  dValue, _ := strconv.Atof64(sValue)
+  return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull}
+}
+
+func NewNullNumeric() Numeric {
+  return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true}
+}
+
+func (p *numeric) Int64() int64 {
+  return p.iValue
+}
+
+func (p *numeric) Int32() int32 {
+  return int32(p.iValue)
+}
+
+func (p *numeric) Int16() int16 {
+  return int16(p.iValue)
+}
+
+func (p *numeric) Byte() byte {
+  return byte(p.iValue)
+}
+
+func (p *numeric) Int() int {
+  return int(p.iValue)
+}
+
+func (p *numeric) Float64() float64 {
+  return p.dValue
+}
+
+func (p *numeric) Float32() float32 {
+  return float32(p.dValue)
+}
+
+func (p *numeric) String() string {
+  return p.sValue
+}
+
+func (p *numeric) isNull() bool {
+  return p.isNil
+}
+
+func init() {
+  INFINITY = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false}
+  NEGATIVE_INFINITY = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false}
+  NAN = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false}
+  ZERO = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false}
+  NUMERIC_NULL = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true}
+}
diff --git a/lib/go/thrift/tprocessor.go b/lib/go/thrift/tprocessor.go
new file mode 100644
index 0000000..d2bb5e4
--- /dev/null
+++ b/lib/go/thrift/tprocessor.go
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+/**
+ * A processor is a generic object which operates upon an input stream and
+ * writes to some output stream.
+ *
+ */
+type TProcessor interface {
+  Process(in, out TProtocol) (bool, TException)
+}
+
+type TProcessorFunction interface {
+  Process(seqId int32, in, out TProtocol) (bool, TException)
+}
diff --git a/lib/go/thrift/tprocessor_factory.go b/lib/go/thrift/tprocessor_factory.go
new file mode 100644
index 0000000..72681ab
--- /dev/null
+++ b/lib/go/thrift/tprocessor_factory.go
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+
+/**
+ * The default processor factory just returns a singleton
+ * instance.
+ */
+type TProcessorFactory interface {
+  GetProcessor(trans TTransport) TProcessor
+}
+
+type tProcessorFactory struct {
+  processor TProcessor
+}
+
+func NewTProcessorFactory(p TProcessor) TProcessorFactory {
+  return &tProcessorFactory{processor: p}
+}
+
+func (p *tProcessorFactory) GetProcessor(trans TTransport) TProcessor {
+  return p.processor
+}
+
+
+/**
+ * The default processor factory just returns a singleton
+ * instance.
+ */
+type TProcessorFunctionFactory interface {
+  GetProcessorFunction(trans TTransport) TProcessorFunction
+}
+
+type tProcessorFunctionFactory struct {
+  processor TProcessorFunction
+}
+
+func NewTProcessorFunctionFactory(p TProcessorFunction) TProcessorFunctionFactory {
+  return &tProcessorFunctionFactory{processor: p}
+}
+
+func (p *tProcessorFunctionFactory) GetProcessorFunction(trans TTransport) TProcessorFunction {
+  return p.processor
+}
diff --git a/lib/go/thrift/tprotocol.go b/lib/go/thrift/tprotocol.go
new file mode 100644
index 0000000..dcb27a8
--- /dev/null
+++ b/lib/go/thrift/tprotocol.go
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+
+const (
+  VERSION_MASK = 0xffff0000
+  VERSION_1    = 0x80010000
+)
+
+type EmptyInterface interface{}
+
+type TProtocol interface {
+  WriteMessageBegin(name string, typeId TMessageType, seqid int32) TProtocolException
+  WriteMessageEnd() TProtocolException
+  WriteStructBegin(name string) TProtocolException
+  WriteStructEnd() TProtocolException
+  WriteFieldBegin(name string, typeId TType, id int16) TProtocolException
+  WriteFieldEnd() TProtocolException
+  WriteFieldStop() TProtocolException
+  WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException
+  WriteMapEnd() TProtocolException
+  WriteListBegin(elemType TType, size int) TProtocolException
+  WriteListEnd() TProtocolException
+  WriteSetBegin(elemType TType, size int) TProtocolException
+  WriteSetEnd() TProtocolException
+  WriteBool(value bool) TProtocolException
+  WriteByte(value byte) TProtocolException
+  WriteI16(value int16) TProtocolException
+  WriteI32(value int32) TProtocolException
+  WriteI64(value int64) TProtocolException
+  WriteDouble(value float64) TProtocolException
+  WriteString(value string) TProtocolException
+  WriteBinary(value []byte) TProtocolException
+
+  ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err TProtocolException)
+  ReadMessageEnd() TProtocolException
+  ReadStructBegin() (name string, err TProtocolException)
+  ReadStructEnd() TProtocolException
+  ReadFieldBegin() (name string, typeId TType, id int16, err TProtocolException)
+  ReadFieldEnd() TProtocolException
+  ReadMapBegin() (keyType TType, valueType TType, size int, err TProtocolException)
+  ReadMapEnd() TProtocolException
+  ReadListBegin() (elemType TType, size int, err TProtocolException)
+  ReadListEnd() TProtocolException
+  ReadSetBegin() (elemType TType, size int, err TProtocolException)
+  ReadSetEnd() TProtocolException
+  ReadBool() (value bool, err TProtocolException)
+  ReadByte() (value byte, err TProtocolException)
+  ReadI16() (value int16, err TProtocolException)
+  ReadI32() (value int32, err TProtocolException)
+  ReadI64() (value int64, err TProtocolException)
+  ReadDouble() (value float64, err TProtocolException)
+  ReadString() (value string, err TProtocolException)
+  ReadBinary() (value []byte, err TProtocolException)
+
+  Skip(fieldType TType) (err TProtocolException)
+  Flush() (err TProtocolException)
+
+  Transport() TTransport
+}
+
+/**
+ * The maximum recursive depth the skip() function will traverse before
+ * throwing a TException.
+ */
+var (
+  MaxSkipDepth = 1<<31 - 1
+)
+
+/**
+ * Specifies the maximum recursive depth that the skip function will
+ * traverse before throwing a TException.  This is a global setting, so
+ * any call to skip in this JVM will enforce this value.
+ *
+ * @param depth  the maximum recursive depth.  A value of 2 would allow
+ *    the skip function to skip a structure or collection with basic children,
+ *    but it would not permit skipping a struct that had a field containing
+ *    a child struct.  A value of 1 would only allow skipping of simple
+ *    types and empty structs/collections.
+ */
+func SetMaxSkipDepth(depth int) {
+  MaxSkipDepth = depth
+}
+
+/**
+ * Skips over the next data element from the provided input TProtocol object.
+ *
+ * @param prot  the protocol object to read from
+ * @param type  the next value will be intepreted as this TType value.
+ */
+func SkipDefaultDepth(prot TProtocol, typeId TType) (err TProtocolException) {
+  return Skip(prot, typeId, MaxSkipDepth)
+}
+
+/**
+ * Skips over the next data element from the provided input TProtocol object.
+ *
+ * @param prot  the protocol object to read from
+ * @param type  the next value will be intepreted as this TType value.
+ * @param maxDepth  this function will only skip complex objects to this
+ *   recursive depth, to prevent Java stack overflow.
+ */
+func Skip(self TProtocol, fieldType TType, maxDepth int) (err TProtocolException) {
+  switch fieldType {
+  case STOP:
+    return
+  case BOOL:
+    _, err = self.ReadBool()
+    return
+  case BYTE:
+    _, err = self.ReadByte()
+    return
+  case I16:
+    _, err = self.ReadI16()
+    return
+  case I32:
+    _, err = self.ReadI32()
+    return
+  case I64:
+    _, err = self.ReadI64()
+    return
+  case DOUBLE:
+    _, err = self.ReadDouble()
+    return
+  case STRING:
+    _, err = self.ReadString()
+    return
+  case STRUCT:
+    {
+      _, err = self.ReadStructBegin()
+      if err != nil {
+        return
+      }
+      for {
+        _, typeId, _, _ := self.ReadFieldBegin()
+        if typeId == STOP {
+          break
+        }
+        Skip(self, typeId, maxDepth-1)
+        self.ReadFieldEnd()
+      }
+      return self.ReadStructEnd()
+    }
+  case MAP:
+    {
+      keyType, valueType, l, err := self.ReadMapBegin()
+      if err != nil {
+        return err
+      }
+      size := int(l)
+      for i := 0; i < size; i++ {
+        Skip(self, keyType, maxDepth-1)
+        self.Skip(valueType)
+      }
+      return self.ReadMapEnd()
+    }
+  case SET:
+    {
+      elemType, l, err := self.ReadSetBegin()
+      if err != nil {
+        return err
+      }
+      size := int(l)
+      for i := 0; i < size; i++ {
+        Skip(self, elemType, maxDepth-1)
+      }
+      return self.ReadSetEnd()
+    }
+  case LIST:
+    {
+      elemType, l, err := self.ReadListBegin()
+      if err != nil {
+        return err
+      }
+      size := int(l)
+      for i := 0; i < size; i++ {
+        Skip(self, elemType, maxDepth-1)
+      }
+      return self.ReadListEnd()
+    }
+  }
+  return nil
+}
diff --git a/lib/go/thrift/tprotocol_exception.go b/lib/go/thrift/tprotocol_exception.go
new file mode 100644
index 0000000..2dac97e
--- /dev/null
+++ b/lib/go/thrift/tprotocol_exception.go
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "encoding/base64"
+  "os"
+)
+
+/**
+ * Protocol exceptions.
+ *
+ */
+type TProtocolException interface {
+  TException
+  TypeId() int
+}
+
+const (
+  UNKNOWN_PROTOCOL_EXCEPTION = 0
+  INVALID_DATA               = 1
+  NEGATIVE_SIZE              = 2
+  SIZE_LIMIT                 = 3
+  BAD_VERSION                = 4
+  NOT_IMPLEMENTED            = 5
+)
+
+type tProtocolException struct {
+  typeId  int
+  message string
+}
+
+func (p *tProtocolException) TypeId() int {
+  return p.typeId
+}
+
+func (p *tProtocolException) String() string {
+  return p.message
+}
+
+func NewTProtocolExceptionDefault() TProtocolException {
+  return NewTProtocolExceptionDefaultType(UNKNOWN_PROTOCOL_EXCEPTION)
+}
+
+func NewTProtocolExceptionDefaultType(t int) TProtocolException {
+  return NewTProtocolException(t, "")
+}
+
+func NewTProtocolExceptionDefaultString(m string) TProtocolException {
+  return NewTProtocolException(UNKNOWN_PROTOCOL_EXCEPTION, m)
+}
+
+func NewTProtocolException(t int, m string) TProtocolException {
+  return &tProtocolException{typeId: t, message: m}
+}
+
+func NewTProtocolExceptionReadField(fieldId int, fieldName string, structName string, e TProtocolException) TProtocolException {
+  t := e.TypeId()
+  if t == UNKNOWN_PROTOCOL_EXCEPTION {
+    t = INVALID_DATA
+  }
+  return NewTProtocolException(t, "Unable to read field "+string(fieldId)+" ("+fieldName+") in "+structName+" due to: "+e.String())
+}
+
+func NewTProtocolExceptionWriteField(fieldId int, fieldName string, structName string, e TProtocolException) TProtocolException {
+  t := e.TypeId()
+  if t == UNKNOWN_PROTOCOL_EXCEPTION {
+    t = INVALID_DATA
+  }
+  return NewTProtocolException(t, "Unable to write field "+string(fieldId)+" ("+fieldName+") in "+structName+" due to: "+e.String())
+}
+
+func NewTProtocolExceptionReadStruct(structName string, e TProtocolException) TProtocolException {
+  t := e.TypeId()
+  if t == UNKNOWN_PROTOCOL_EXCEPTION {
+    t = INVALID_DATA
+  }
+  return NewTProtocolException(t, "Unable to read struct "+structName+" due to: "+e.String())
+}
+
+func NewTProtocolExceptionWriteStruct(structName string, e TProtocolException) TProtocolException {
+  t := e.TypeId()
+  if t == UNKNOWN_PROTOCOL_EXCEPTION {
+    t = INVALID_DATA
+  }
+  return NewTProtocolException(t, "Unable to write struct "+structName+" due to: "+e.String())
+}
+
+func NewTProtocolExceptionFromOsError(e os.Error) TProtocolException {
+  if e == nil {
+    return nil
+  }
+  if t, ok := e.(TProtocolException); ok {
+    return t
+  }
+  if te, ok := e.(TTransportException); ok {
+    return NewTProtocolExceptionFromTransportException(te)
+  }
+  if _, ok := e.(base64.CorruptInputError); ok {
+    return NewTProtocolException(INVALID_DATA, e.String())
+  }
+  return NewTProtocolExceptionDefaultString(e.String())
+}
+
+func NewTProtocolExceptionFromTransportException(e TTransportException) TProtocolException {
+  if e == nil {
+    return nil
+  }
+  if t, ok := e.(TProtocolException); ok {
+    return t
+  }
+  return NewTProtocolExceptionDefaultString(e.String())
+}
diff --git a/lib/go/thrift/tprotocol_factory.go b/lib/go/thrift/tprotocol_factory.go
new file mode 100644
index 0000000..2eed2c2
--- /dev/null
+++ b/lib/go/thrift/tprotocol_factory.go
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+/**
+ * Factory interface for constructing protocol instances.
+ *
+ */
+type TProtocolFactory interface {
+  GetProtocol(trans TTransport) TProtocol
+}
diff --git a/lib/go/thrift/tprotocol_test.go b/lib/go/thrift/tprotocol_test.go
new file mode 100644
index 0000000..22d6ad6
--- /dev/null
+++ b/lib/go/thrift/tprotocol_test.go
@@ -0,0 +1,1817 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+  "http"
+  "math"
+  "net"
+  "io"
+  "os"
+  "bytes"
+  "fmt"
+)
+
+const PROTOCOL_BINARY_DATA_SIZE = 155
+
+var (
+  data           string // test data for writing
+  protocol_bdata []byte // test data for writing; same as data
+  BOOL_VALUES    []bool
+  BYTE_VALUES    []byte
+  INT16_VALUES   []int16
+  INT32_VALUES   []int32
+  INT64_VALUES   []int64
+  DOUBLE_VALUES  []float64
+  STRING_VALUES  []string
+)
+
+
+func init() {
+  protocol_bdata = make([]byte, PROTOCOL_BINARY_DATA_SIZE)
+  for i := 0; i < PROTOCOL_BINARY_DATA_SIZE; i++ {
+    protocol_bdata[i] = byte((i + 'a') % 255)
+  }
+  data = string(protocol_bdata)
+  BOOL_VALUES = []bool{false, true, false, false, true}
+  BYTE_VALUES = []byte{117, 0, 1, 32, 127, 128, 255}
+  INT16_VALUES = []int16{459, 0, 1, -1, -128, 127, 32767, -32768}
+  INT32_VALUES = []int32{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535}
+  INT64_VALUES = []int64{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535, 34359738481, -35184372088719, -9223372036854775808, 9223372036854775807}
+  DOUBLE_VALUES = []float64{459.3, 0.0, -1.0, 1.0, 0.5, 0.3333, 3.14159, 1.537e-38, 1.673e25, 6.02214179e23, -6.02214179e23, INFINITY.Float64(), NEGATIVE_INFINITY.Float64(), NAN.Float64()}
+  STRING_VALUES = []string{"", "a", "st[uf]f", "st,u:ff with spaces", "stuff\twith\nescape\\characters'...\"lots{of}fun</xml>"}
+}
+
+type HTTPEchoServer struct{}
+
+func (p *HTTPEchoServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+  w.WriteHeader(http.StatusOK)
+  io.Copy(w, req.Body)
+}
+
+func HttpClientSetupForTest(t *testing.T) (net.Listener, net.Addr) {
+  addr, err := FindAvailableTCPServerPort(40000)
+  if err != nil {
+    t.Fatalf("Unable to find available tcp port addr: %s", err)
+  }
+  l, err := net.Listen(addr.Network(), addr.String())
+  if err != nil {
+    t.Fatalf("Unable to setup tcp listener on %s: %s", addr.String(), err)
+  }
+  go http.Serve(l, &HTTPEchoServer{})
+  return l, addr
+}
+
+
+func ReadWriteProtocolTest(t *testing.T, protocolFactory TProtocolFactory) {
+  buf := bytes.NewBuffer(make([]byte, 0, 1024))
+  l, addr := HttpClientSetupForTest(t)
+  transports := []TTransportFactory{
+    NewTMemoryBufferTransportFactory(1024),
+    NewTIOStreamTransportFactory(buf, buf, true),
+    NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024)),
+    NewTHttpPostClientTransportFactory("http://" + addr.String()),
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteBool(t, p, trans)
+    trans.Close()
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteByte(t, p, trans)
+    trans.Close()
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteI16(t, p, trans)
+    trans.Close()
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteI32(t, p, trans)
+    trans.Close()
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteI64(t, p, trans)
+    trans.Close()
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteDouble(t, p, trans)
+    trans.Close()
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteString(t, p, trans)
+    trans.Close()
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteBinary(t, p, trans)
+    trans.Close()
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteWork(t, p, trans)
+    trans.Close()
+  }
+  for _, tf := range transports {
+    trans := tf.GetTransport(nil)
+    p := protocolFactory.GetProtocol(trans)
+    ReadWriteCalculate(t, p, trans)
+    trans.Close()
+  }
+
+  // this test doesn't work in all cases due to EOF issues between
+  // buffer read and buffer write when using the same bufio for both
+  //for _, tf := range transports {
+  //  trans := tf.GetTransport(nil)
+  //  p := GetProtocol(trans);
+  //  ReadWriteI64(t, p, trans);
+  //  ReadWriteDouble(t, p, trans);
+  //  ReadWriteBinary(t, p, trans);
+  //  ReadWriteByte(t, p, trans);
+  //  trans.Close()
+  //}
+
+  l.Close()
+}
+
+func ReadWriteBool(t *testing.T, p TProtocol, trans TTransport) {
+  thetype := TType(BOOL)
+  thelen := len(BOOL_VALUES)
+  err := p.WriteListBegin(thetype, thelen)
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteBool", p, trans, err, thetype)
+  }
+  for k, v := range BOOL_VALUES {
+    err = p.WriteBool(v)
+    if err != nil {
+      t.Errorf("%s: %T %T %q Error writing bool in list at index %d: %q", "ReadWriteBool", p, trans, err, k, v)
+    }
+  }
+  p.WriteListEnd()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES)
+  }
+  p.Flush()
+  thetype2, thelen2, err := p.ReadListBegin()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteBool", p, trans, err, BOOL_VALUES)
+  }
+  _, ok := p.(*TSimpleJSONProtocol)
+  if !ok {
+    if thetype != thetype2 {
+      t.Errorf("%s: %T %T type %s != type %s", "ReadWriteBool", p, trans, thetype, thetype2)
+    }
+    if thelen != thelen2 {
+      t.Errorf("%s: %T %T len %s != len %s", "ReadWriteBool", p, trans, thelen, thelen2)
+    }
+  }
+  for k, v := range BOOL_VALUES {
+    value, err := p.ReadBool()
+    if err != nil {
+      t.Errorf("%s: %T %T %q Error reading bool at index %d: %q", "ReadWriteBool", p, trans, err, k, v)
+    }
+    if v != value {
+      t.Errorf("%s: index %d %q %q %q != %q", "ReadWriteBool", k, p, trans, v, value)
+    }
+  }
+  err = p.ReadListEnd()
+  if err != nil {
+    t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteBool", p, trans, err)
+  }
+}
+
+func ReadWriteByte(t *testing.T, p TProtocol, trans TTransport) {
+  thetype := TType(BYTE)
+  thelen := len(BYTE_VALUES)
+  err := p.WriteListBegin(thetype, thelen)
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteByte", p, trans, err, thetype)
+  }
+  for k, v := range BYTE_VALUES {
+    err = p.WriteByte(v)
+    if err != nil {
+      t.Errorf("%s: %T %T %q Error writing byte in list at index %d: %q", "ReadWriteByte", p, trans, err, k, v)
+    }
+  }
+  err = p.WriteListEnd()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES)
+  }
+  err = p.Flush()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error flushing list of bytes: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES)
+  }
+  thetype2, thelen2, err := p.ReadListBegin()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES)
+  }
+  _, ok := p.(*TSimpleJSONProtocol)
+  if !ok {
+    if thetype != thetype2 {
+      t.Errorf("%s: %T %T type %s != type %s", "ReadWriteByte", p, trans, thetype, thetype2)
+    }
+    if thelen != thelen2 {
+      t.Errorf("%s: %T %T len %s != len %s", "ReadWriteByte", p, trans, thelen, thelen2)
+    }
+  }
+  for k, v := range BYTE_VALUES {
+    value, err := p.ReadByte()
+    if err != nil {
+      t.Errorf("%s: %T %T %q Error reading byte at index %d: %q", "ReadWriteByte", p, trans, err, k, v)
+    }
+    if v != value {
+      t.Errorf("%s: %T %T %d != %d", "ReadWriteByte", p, trans, v, value)
+    }
+  }
+  err = p.ReadListEnd()
+  if err != nil {
+    t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteByte", p, trans, err)
+  }
+}
+
+func ReadWriteI16(t *testing.T, p TProtocol, trans TTransport) {
+  thetype := TType(I16)
+  thelen := len(INT16_VALUES)
+  p.WriteListBegin(thetype, thelen)
+  for _, v := range INT16_VALUES {
+    p.WriteI16(v)
+  }
+  p.WriteListEnd()
+  p.Flush()
+  thetype2, thelen2, err := p.ReadListBegin()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI16", p, trans, err, INT16_VALUES)
+  }
+  _, ok := p.(*TSimpleJSONProtocol)
+  if !ok {
+    if thetype != thetype2 {
+      t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI16", p, trans, thetype, thetype2)
+    }
+    if thelen != thelen2 {
+      t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI16", p, trans, thelen, thelen2)
+    }
+  }
+  for k, v := range INT16_VALUES {
+    value, err := p.ReadI16()
+    if err != nil {
+      t.Errorf("%s: %T %T %q Error reading int16 at index %d: %q", "ReadWriteI16", p, trans, err, k, v)
+    }
+    if v != value {
+      t.Errorf("%s: %T %T %d != %d", "ReadWriteI16", p, trans, v, value)
+    }
+  }
+  err = p.ReadListEnd()
+  if err != nil {
+    t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI16", p, trans, err)
+  }
+}
+
+func ReadWriteI32(t *testing.T, p TProtocol, trans TTransport) {
+  thetype := TType(I32)
+  thelen := len(INT32_VALUES)
+  p.WriteListBegin(thetype, thelen)
+  for _, v := range INT32_VALUES {
+    p.WriteI32(v)
+  }
+  p.WriteListEnd()
+  p.Flush()
+  thetype2, thelen2, err := p.ReadListBegin()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI32", p, trans, err, INT32_VALUES)
+  }
+  _, ok := p.(*TSimpleJSONProtocol)
+  if !ok {
+    if thetype != thetype2 {
+      t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI32", p, trans, thetype, thetype2)
+    }
+    if thelen != thelen2 {
+      t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI32", p, trans, thelen, thelen2)
+    }
+  }
+  for k, v := range INT32_VALUES {
+    value, err := p.ReadI32()
+    if err != nil {
+      t.Errorf("%s: %T %T %q Error reading int32 at index %d: %q", "ReadWriteI32", p, trans, err, k, v)
+    }
+    if v != value {
+      t.Errorf("%s: %T %T %d != %d", "ReadWriteI32", p, trans, v, value)
+    }
+  }
+  if err != nil {
+    t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI32", p, trans, err)
+  }
+}
+
+func ReadWriteI64(t *testing.T, p TProtocol, trans TTransport) {
+  thetype := TType(I64)
+  thelen := len(INT64_VALUES)
+  p.WriteListBegin(thetype, thelen)
+  for _, v := range INT64_VALUES {
+    p.WriteI64(v)
+  }
+  p.WriteListEnd()
+  p.Flush()
+  thetype2, thelen2, err := p.ReadListBegin()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI64", p, trans, err, INT64_VALUES)
+  }
+  _, ok := p.(*TSimpleJSONProtocol)
+  if !ok {
+    if thetype != thetype2 {
+      t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI64", p, trans, thetype, thetype2)
+    }
+    if thelen != thelen2 {
+      t.Errorf("%s: %T %T len %s != len %s", "ReadWriteI64", p, trans, thelen, thelen2)
+    }
+  }
+  for k, v := range INT64_VALUES {
+    value, err := p.ReadI64()
+    if err != nil {
+      t.Errorf("%s: %T %T %q Error reading int64 at index %d: %q", "ReadWriteI64", p, trans, err, k, v)
+    }
+    if v != value {
+      t.Errorf("%s: %T %T %q != %q", "ReadWriteI64", p, trans, v, value)
+    }
+  }
+  if err != nil {
+    t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI64", p, trans, err)
+  }
+}
+
+func ReadWriteDouble(t *testing.T, p TProtocol, trans TTransport) {
+  thetype := TType(DOUBLE)
+  thelen := len(DOUBLE_VALUES)
+  p.WriteListBegin(thetype, thelen)
+  for _, v := range DOUBLE_VALUES {
+    p.WriteDouble(v)
+  }
+  p.WriteListEnd()
+  p.Flush()
+  wrotebuffer := ""
+  if memtrans, ok := trans.(*TMemoryBuffer); ok {
+    wrotebuffer = memtrans.String()
+  }
+  thetype2, thelen2, err := p.ReadListBegin()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error reading list: %q, wrote: %v", "ReadWriteDouble", p, trans, err, DOUBLE_VALUES, wrotebuffer)
+  }
+  if thetype != thetype2 {
+    t.Errorf("%s: %T %T type %s != type %s", "ReadWriteDouble", p, trans, thetype, thetype2)
+  }
+  if thelen != thelen2 {
+    t.Errorf("%s: %T %T len %s != len %s", "ReadWriteDouble", p, trans, thelen, thelen2)
+  }
+  for k, v := range DOUBLE_VALUES {
+    value, err := p.ReadDouble()
+    if err != nil {
+      t.Errorf("%s: %T %T %q Error reading double at index %d: %q", "ReadWriteDouble", p, trans, err, k, v)
+    }
+    if math.IsNaN(v) {
+      if !math.IsNaN(value) {
+        t.Errorf("%s: %T %T math.IsNaN(%q) != math.IsNaN(%q)", "ReadWriteDouble", p, trans, v, value)
+      }
+    } else if v != value {
+      t.Errorf("%s: %T %T %v != %q", "ReadWriteDouble", p, trans, v, value)
+    }
+  }
+  err = p.ReadListEnd()
+  if err != nil {
+    t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteDouble", p, trans, err)
+  }
+}
+
+func ReadWriteString(t *testing.T, p TProtocol, trans TTransport) {
+  thetype := TType(STRING)
+  thelen := len(STRING_VALUES)
+  p.WriteListBegin(thetype, thelen)
+  for _, v := range STRING_VALUES {
+    p.WriteString(v)
+  }
+  p.WriteListEnd()
+  p.Flush()
+  thetype2, thelen2, err := p.ReadListBegin()
+  if err != nil {
+    t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteString", p, trans, err, STRING_VALUES)
+  }
+  _, ok := p.(*TSimpleJSONProtocol)
+  if !ok {
+    if thetype != thetype2 {
+      t.Errorf("%s: %T %T type %s != type %s", "ReadWriteString", p, trans, thetype, thetype2)
+    }
+    if thelen != thelen2 {
+      t.Errorf("%s: %T %T len %s != len %s", "ReadWriteString", p, trans, thelen, thelen2)
+    }
+  }
+  for k, v := range STRING_VALUES {
+    value, err := p.ReadString()
+    if err != nil {
+      t.Errorf("%s: %T %T %q Error reading string at index %d: %q", "ReadWriteString", p, trans, err, k, v)
+    }
+    if v != value {
+      t.Errorf("%s: %T %T %d != %d", "ReadWriteString", p, trans, v, value)
+    }
+  }
+  if err != nil {
+    t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteString", p, trans, err)
+  }
+}
+
+
+func ReadWriteBinary(t *testing.T, p TProtocol, trans TTransport) {
+  v := protocol_bdata
+  p.WriteBinary(v)
+  p.Flush()
+  value, err := p.ReadBinary()
+  if err != nil {
+    t.Errorf("%s: %T %T Unable to read binary: %s", "ReadWriteBinary", p, trans, err.String())
+  }
+  if len(v) != len(value) {
+    t.Errorf("%s: %T %T len(v) != len(value)... %d != %d", "ReadWriteBinary", p, trans, len(v), len(value))
+  } else {
+    for i := 0; i < len(v); i++ {
+      if v[i] != value[i] {
+        t.Errorf("%s: %T %T %s != %s", "ReadWriteBinary", p, trans, v, value)
+      }
+    }
+  }
+}
+
+
+func ReadWriteWork(t *testing.T, p TProtocol, trans TTransport) {
+  thetype := "struct"
+  orig := NewWork()
+  orig.Num1 = 25
+  orig.Num2 = 102
+  orig.Op = ADD
+  orig.Comment = "Add: 25 + 102"
+  return
+  if e := orig.Write(p); e != nil {
+    t.Fatalf("Unable to write %s value %#v due to error: %s", thetype, orig, e.String())
+  }
+  read := NewWork()
+  e := read.Read(p)
+  if e != nil {
+    t.Fatalf("Unable to read %s due to error: %s", thetype, e.String())
+  }
+  if !orig.Equals(read) {
+    t.Fatalf("Original Write != Read: %#v != %#v ", orig, read)
+  }
+}
+
+
+func ReadWriteCalculate(t *testing.T, p TProtocol, trans TTransport) {
+  messageName := "calculate"
+  logid := int32(12)
+  seqId := int32(35)
+  w := NewWork()
+  w.Num1 = 25
+  w.Num2 = 102
+  w.Op = ADD
+  w.Comment = "Add: 25 + 102"
+
+  args31 := NewCalculateArgs()
+  args31.Logid = logid
+  args31.W = w
+  p.WriteMessageBegin(messageName, CALL, seqId)
+  if err := args31.Write(p); err != nil {
+    t.Fatalf("%s: %T %T Unable to write message: %s", messageName, p, trans, err.String())
+  }
+  p.WriteMessageEnd()
+  p.Transport().Flush()
+
+  name, ttype, seqid, err1 := p.ReadMessageBegin()
+  if err1 != nil {
+    t.Fatalf("%s: %T %T Unable to read message begin: %s", messageName, p, trans, err1.String())
+  }
+  if name != messageName {
+    t.Errorf("%s: %T %T Expected message named \"%s\", but was: \"%s\"", messageName, p, trans, messageName, name)
+  }
+  if ttype != CALL {
+    t.Errorf("%s: %T %T Expected message type \"%s\", but was: \"%s\"", messageName, p, trans, CALL, ttype)
+  }
+  if seqid != seqId {
+    t.Errorf("%s: %T %T Expected message type \"%s\", but was: \"%s\"", messageName, p, trans, seqId, seqid)
+  }
+  calcArgs := NewCalculateArgs()
+  err2 := calcArgs.Read(p)
+  if !args31.Equals(calcArgs) {
+    //cmp1, _ := args31.W.CompareTo(calcArgs.W)
+    cmp2, ok := args31.CompareTo(calcArgs)
+    t.Errorf("%s: %T %T Calculate args not as expected, %T vs %T, cmp: %#v, ok: %#v, equals: %#v", messageName, p, trans, args31, calcArgs, cmp2, ok, args31.Equals(calcArgs))
+  }
+  if err2 != nil {
+    t.Fatalf("%s: %T %T Unable to read message end: %s", messageName, p, trans, err2.String())
+  }
+  err3 := p.ReadMessageEnd()
+  if err3 != nil {
+    t.Fatalf("%s: %T %T Unable to read message end: %s", messageName, p, trans, err3.String())
+  }
+}
+
+
+/**
+ *You can define enums, which are just 32 bit integers. Values are optional
+ *and start at 1 if not supplied, C style again.
+ */
+type Operation int
+
+const (
+  ADD      Operation = 1
+  SUBTRACT Operation = 2
+  MULTIPLY Operation = 3
+  DIVIDE   Operation = 4
+)
+
+func (p Operation) String() string {
+  switch p {
+  case ADD:
+    return "ADD"
+  case SUBTRACT:
+    return "SUBTRACT"
+  case MULTIPLY:
+    return "MULTIPLY"
+  case DIVIDE:
+    return "DIVIDE"
+  }
+  return ""
+}
+
+func FromOperationString(s string) Operation {
+  switch s {
+  case "ADD":
+    return ADD
+  case "SUBTRACT":
+    return SUBTRACT
+  case "MULTIPLY":
+    return MULTIPLY
+  case "DIVIDE":
+    return DIVIDE
+  }
+  return Operation(-10000)
+}
+
+func (p Operation) Value() int {
+  return int(p)
+}
+
+func (p Operation) IsEnum() bool {
+  return true
+}
+
+/**
+ *Thrift lets you do typedefs to get pretty names for your types. Standard
+ *C style here.
+ */
+type MyInteger int32
+
+const INT32CONSTANT = 9853
+
+var MAPCONSTANT TMap
+/**
+ * Structs are the basic complex data structures. They are comprised of fields
+ * which each have an integer identifier, a type, a symbolic name, and an
+ * optional default value.
+ * 
+ * Fields can be declared "optional", which ensures they will not be included
+ * in the serialized output if they aren't set.  Note that this requires some
+ * manual management in some languages.
+ * 
+ * Attributes:
+ *  - Num1
+ *  - Num2
+ *  - Op
+ *  - Comment
+ */
+type Work struct {
+  TStruct
+  _       interface{} "num1"    // nil # 0
+  Num1    int32       "num1"    // 1
+  Num2    int32       "num2"    // 2
+  Op      Operation   "op"      // 3
+  Comment string      "comment" // 4
+}
+
+func NewWork() *Work {
+  output := &Work{
+    TStruct: NewTStruct("Work", []TField{
+      NewTField("num1", I32, 1),
+      NewTField("num2", I32, 2),
+      NewTField("op", I32, 3),
+      NewTField("comment", STRING, 4),
+    }),
+  }
+  {
+    output.Num1 = 0
+  }
+  return output
+}
+
+func (p *Work) Read(iprot TProtocol) (err TProtocolException) {
+  _, err = iprot.ReadStructBegin()
+  if err != nil {
+    return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+  }
+  for {
+    fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+    if fieldId < 0 {
+      fieldId = int16(p.FieldIdFromFieldName(fieldName))
+    } else if fieldName == "" {
+      fieldName = p.FieldNameFromFieldId(int(fieldId))
+    }
+    if fieldTypeId == GENERIC {
+      fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId()
+    }
+    if err != nil {
+      return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+    }
+    if fieldTypeId == STOP {
+      break
+    }
+    if fieldId == 1 || fieldName == "num1" {
+      if fieldTypeId == I32 {
+        err = p.ReadField1(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField1(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else if fieldId == 2 || fieldName == "num2" {
+      if fieldTypeId == I32 {
+        err = p.ReadField2(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField2(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else if fieldId == 3 || fieldName == "op" {
+      if fieldTypeId == I32 {
+        err = p.ReadField3(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField3(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else if fieldId == 4 || fieldName == "comment" {
+      if fieldTypeId == STRING {
+        err = p.ReadField4(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField4(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else {
+      err = iprot.Skip(fieldTypeId)
+      if err != nil {
+        return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+      }
+    }
+    err = iprot.ReadFieldEnd()
+    if err != nil {
+      return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+    }
+  }
+  err = iprot.ReadStructEnd()
+  if err != nil {
+    return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *Work) ReadField1(iprot TProtocol) (err TProtocolException) {
+  v4, err5 := iprot.ReadI32()
+  if err5 != nil {
+    return NewTProtocolExceptionReadField(1, "num1", p.ThriftName(), err5)
+  }
+  p.Num1 = v4
+  return err
+}
+
+func (p *Work) ReadFieldNum1(iprot TProtocol) TProtocolException {
+  return p.ReadField1(iprot)
+}
+
+func (p *Work) ReadField2(iprot TProtocol) (err TProtocolException) {
+  v6, err7 := iprot.ReadI32()
+  if err7 != nil {
+    return NewTProtocolExceptionReadField(2, "num2", p.ThriftName(), err7)
+  }
+  p.Num2 = v6
+  return err
+}
+
+func (p *Work) ReadFieldNum2(iprot TProtocol) TProtocolException {
+  return p.ReadField2(iprot)
+}
+
+func (p *Work) ReadField3(iprot TProtocol) (err TProtocolException) {
+  v8, err9 := iprot.ReadI32()
+  if err9 != nil {
+    return NewTProtocolExceptionReadField(3, "op", p.ThriftName(), err9)
+  }
+  p.Op = Operation(v8)
+  return err
+}
+
+func (p *Work) ReadFieldOp(iprot TProtocol) TProtocolException {
+  return p.ReadField3(iprot)
+}
+
+func (p *Work) ReadField4(iprot TProtocol) (err TProtocolException) {
+  v10, err11 := iprot.ReadString()
+  if err11 != nil {
+    return NewTProtocolExceptionReadField(4, "comment", p.ThriftName(), err11)
+  }
+  p.Comment = v10
+  return err
+}
+
+func (p *Work) ReadFieldComment(iprot TProtocol) TProtocolException {
+  return p.ReadField4(iprot)
+}
+
+func (p *Work) Write(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteStructBegin("Work")
+  if err != nil {
+    return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+  }
+  err = p.WriteField1(oprot)
+  if err != nil {
+    return err
+  }
+  err = p.WriteField2(oprot)
+  if err != nil {
+    return err
+  }
+  err = p.WriteField3(oprot)
+  if err != nil {
+    return err
+  }
+  err = p.WriteField4(oprot)
+  if err != nil {
+    return err
+  }
+  err = oprot.WriteFieldStop()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err)
+  }
+  err = oprot.WriteStructEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *Work) WriteField1(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteFieldBegin("num1", I32, 1)
+  if err != nil {
+    return NewTProtocolExceptionWriteField(1, "num1", p.ThriftName(), err)
+  }
+  err = oprot.WriteI32(int32(p.Num1))
+  if err != nil {
+    return NewTProtocolExceptionWriteField(1, "num1", p.ThriftName(), err)
+  }
+  err = oprot.WriteFieldEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(1, "num1", p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *Work) WriteFieldNum1(oprot TProtocol) TProtocolException {
+  return p.WriteField1(oprot)
+}
+
+func (p *Work) WriteField2(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteFieldBegin("num2", I32, 2)
+  if err != nil {
+    return NewTProtocolExceptionWriteField(2, "num2", p.ThriftName(), err)
+  }
+  err = oprot.WriteI32(int32(p.Num2))
+  if err != nil {
+    return NewTProtocolExceptionWriteField(2, "num2", p.ThriftName(), err)
+  }
+  err = oprot.WriteFieldEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(2, "num2", p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *Work) WriteFieldNum2(oprot TProtocol) TProtocolException {
+  return p.WriteField2(oprot)
+}
+
+func (p *Work) WriteField3(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteFieldBegin("op", I32, 3)
+  if err != nil {
+    return NewTProtocolExceptionWriteField(3, "op", p.ThriftName(), err)
+  }
+  err = oprot.WriteI32(int32(p.Op))
+  if err != nil {
+    return NewTProtocolExceptionWriteField(3, "op", p.ThriftName(), err)
+  }
+  err = oprot.WriteFieldEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(3, "op", p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *Work) WriteFieldOp(oprot TProtocol) TProtocolException {
+  return p.WriteField3(oprot)
+}
+
+func (p *Work) WriteField4(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteFieldBegin("comment", STRING, 4)
+  if err != nil {
+    return NewTProtocolExceptionWriteField(4, "comment", p.ThriftName(), err)
+  }
+  err = oprot.WriteString(string(p.Comment))
+  if err != nil {
+    return NewTProtocolExceptionWriteField(4, "comment", p.ThriftName(), err)
+  }
+  err = oprot.WriteFieldEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(4, "comment", p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *Work) WriteFieldComment(oprot TProtocol) TProtocolException {
+  return p.WriteField4(oprot)
+}
+
+func (p *Work) TStructName() string {
+  return "Work"
+}
+
+func (p *Work) ThriftName() string {
+  return "Work"
+}
+
+func (p *Work) String() string {
+  if p == nil {
+    return "<nil>"
+  }
+  return fmt.Sprintf("Work(%+v)", *p)
+}
+
+func (p *Work) CompareTo(other interface{}) (int, bool) {
+  if other == nil {
+    return 1, true
+  }
+  data, ok := other.(*Work)
+  if !ok {
+    return 0, false
+  }
+  if p.Num1 != data.Num1 {
+    if p.Num1 < data.Num1 {
+      return -1, true
+    }
+    return 1, true
+  }
+  if p.Num2 != data.Num2 {
+    if p.Num2 < data.Num2 {
+      return -1, true
+    }
+    return 1, true
+  }
+  if p.Op != data.Op {
+    if p.Op < data.Op {
+      return -1, true
+    }
+    return 1, true
+  }
+  if p.Comment != data.Comment {
+    if p.Comment < data.Comment {
+      return -1, true
+    }
+    return 1, true
+  }
+  return 0, true
+}
+
+func (p *Work) AttributeByFieldId(id int) interface{} {
+  switch id {
+  default:
+    return nil
+  case 1:
+    return p.Num1
+  case 2:
+    return p.Num2
+  case 3:
+    return p.Op
+  case 4:
+    return p.Comment
+  }
+  return nil
+}
+
+func (p *Work) TStructFields() TFieldContainer {
+  return NewTFieldContainer([]TField{
+    NewTField("num1", I32, 1),
+    NewTField("num2", I32, 2),
+    NewTField("op", I32, 3),
+    NewTField("comment", STRING, 4),
+  })
+}
+
+
+type ICalculator interface {
+  /**
+   * Parameters:
+   *  - Key
+   */
+  Calculate(logid int32, w *Work) (retval30 int32, ouch *InvalidOperation, err os.Error)
+}
+
+type CalculatorClient struct {
+  Transport       TTransport
+  ProtocolFactory TProtocolFactory
+  InputProtocol   TProtocol
+  OutputProtocol  TProtocol
+  SeqId           int32
+}
+
+func NewCalculatorClientFactory(t TTransport, f TProtocolFactory) *CalculatorClient {
+  return &CalculatorClient{Transport: t,
+    ProtocolFactory: f,
+    InputProtocol:   f.GetProtocol(t),
+    OutputProtocol:  f.GetProtocol(t),
+    SeqId:           0,
+  }
+}
+
+func NewCalculatorClientProtocol(t TTransport, iprot TProtocol, oprot TProtocol) *CalculatorClient {
+  return &CalculatorClient{Transport: t,
+    ProtocolFactory: nil,
+    InputProtocol:   iprot,
+    OutputProtocol:  oprot,
+    SeqId:           0,
+  }
+}
+
+
+/**
+ * Parameters:
+ *  - Logid
+ *  - W
+ */
+func (p *CalculatorClient) Calculate(logid int32, w *Work) (retval30 int32, ouch *InvalidOperation, err os.Error) {
+  err = p.SendCalculate(logid, w)
+  if err != nil {
+    return
+  }
+  return p.RecvCalculate()
+}
+
+func (p *CalculatorClient) SendCalculate(logid int32, w *Work) (err os.Error) {
+  oprot := p.OutputProtocol
+  if oprot != nil {
+    oprot = p.ProtocolFactory.GetProtocol(p.Transport)
+    p.OutputProtocol = oprot
+  }
+  oprot.WriteMessageBegin("calculate", CALL, p.SeqId)
+  args31 := NewCalculateArgs()
+  args31.Logid = logid
+  args31.W = w
+  err = args31.Write(oprot)
+  oprot.WriteMessageEnd()
+  oprot.Transport().Flush()
+  return
+}
+
+
+func (p *CalculatorClient) RecvCalculate() (value int32, ouch *InvalidOperation, err os.Error) {
+  iprot := p.InputProtocol
+  if iprot == nil {
+    iprot = p.ProtocolFactory.GetProtocol(p.Transport)
+    p.InputProtocol = iprot
+  }
+  _, mTypeId, _, err := iprot.ReadMessageBegin()
+  if err != nil {
+    return
+  }
+  if mTypeId == EXCEPTION {
+    error33 := NewTApplicationExceptionDefault()
+    error34, err := error33.Read(iprot)
+    if err != nil {
+      return
+    }
+    if err = iprot.ReadMessageEnd(); err != nil {
+      return
+    }
+    err = error34
+    return
+  }
+  result32 := NewCalculateResult()
+  err = result32.Read(iprot)
+  iprot.ReadMessageEnd()
+  value = result32.Success
+  if result32.Ouch != nil {
+    ouch = result32.Ouch
+  }
+  return
+}
+
+
+/**
+ * Attributes:
+ *  - Logid
+ *  - W
+ */
+type CalculateArgs struct {
+  TStruct
+  _     interface{} "logid" // nil # 0
+  Logid int32       "logid" // 1
+  W     *Work       "w"     // 2
+}
+
+func NewCalculateArgs() *CalculateArgs {
+  output := &CalculateArgs{
+    TStruct: NewTStruct("calculate_args", []TField{
+      NewTField("logid", I32, 1),
+      NewTField("w", STRUCT, 2),
+    }),
+  }
+  {
+  }
+  return output
+}
+
+func (p *CalculateArgs) Read(iprot TProtocol) (err TProtocolException) {
+  _, err = iprot.ReadStructBegin()
+  if err != nil {
+    return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+  }
+  for {
+    fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+    if fieldId < 0 {
+      fieldId = int16(p.FieldIdFromFieldName(fieldName))
+    } else if fieldName == "" {
+      fieldName = p.FieldNameFromFieldId(int(fieldId))
+    }
+    if fieldTypeId == GENERIC {
+      fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId()
+    }
+    if err != nil {
+      return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+    }
+    if fieldTypeId == STOP {
+      break
+    }
+    if fieldId == 1 || fieldName == "logid" {
+      if fieldTypeId == I32 {
+        err = p.ReadField1(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField1(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else if fieldId == 2 || fieldName == "w" {
+      if fieldTypeId == STRUCT {
+        err = p.ReadField2(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField2(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else {
+      err = iprot.Skip(fieldTypeId)
+      if err != nil {
+        return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+      }
+    }
+    err = iprot.ReadFieldEnd()
+    if err != nil {
+      return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+    }
+  }
+  err = iprot.ReadStructEnd()
+  if err != nil {
+    return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *CalculateArgs) ReadField1(iprot TProtocol) (err TProtocolException) {
+  v47, err48 := iprot.ReadI32()
+  if err48 != nil {
+    return NewTProtocolExceptionReadField(1, "logid", p.ThriftName(), err48)
+  }
+  p.Logid = v47
+  return err
+}
+
+func (p *CalculateArgs) ReadFieldLogid(iprot TProtocol) TProtocolException {
+  return p.ReadField1(iprot)
+}
+
+func (p *CalculateArgs) ReadField2(iprot TProtocol) (err TProtocolException) {
+  p.W = NewWork()
+  err51 := p.W.Read(iprot)
+  if err51 != nil {
+    return NewTProtocolExceptionReadStruct("p.WWork", err51)
+  }
+  return err
+}
+
+func (p *CalculateArgs) ReadFieldW(iprot TProtocol) TProtocolException {
+  return p.ReadField2(iprot)
+}
+
+func (p *CalculateArgs) Write(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteStructBegin("calculate_args")
+  if err != nil {
+    return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+  }
+  err = p.WriteField1(oprot)
+  if err != nil {
+    return err
+  }
+  err = p.WriteField2(oprot)
+  if err != nil {
+    return err
+  }
+  err = oprot.WriteFieldStop()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err)
+  }
+  err = oprot.WriteStructEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *CalculateArgs) WriteField1(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteFieldBegin("logid", I32, 1)
+  if err != nil {
+    return NewTProtocolExceptionWriteField(1, "logid", p.ThriftName(), err)
+  }
+  err = oprot.WriteI32(int32(p.Logid))
+  if err != nil {
+    return NewTProtocolExceptionWriteField(1, "logid", p.ThriftName(), err)
+  }
+  err = oprot.WriteFieldEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(1, "logid", p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *CalculateArgs) WriteFieldLogid(oprot TProtocol) TProtocolException {
+  return p.WriteField1(oprot)
+}
+
+func (p *CalculateArgs) WriteField2(oprot TProtocol) (err TProtocolException) {
+  if p.W != nil {
+    err = oprot.WriteFieldBegin("w", STRUCT, 2)
+    if err != nil {
+      return NewTProtocolExceptionWriteField(2, "w", p.ThriftName(), err)
+    }
+    err = p.W.Write(oprot)
+    if err != nil {
+      return NewTProtocolExceptionWriteStruct("Work", err)
+    }
+    err = oprot.WriteFieldEnd()
+    if err != nil {
+      return NewTProtocolExceptionWriteField(2, "w", p.ThriftName(), err)
+    }
+  }
+  return err
+}
+
+func (p *CalculateArgs) WriteFieldW(oprot TProtocol) TProtocolException {
+  return p.WriteField2(oprot)
+}
+
+func (p *CalculateArgs) TStructName() string {
+  return "CalculateArgs"
+}
+
+func (p *CalculateArgs) ThriftName() string {
+  return "calculate_args"
+}
+
+func (p *CalculateArgs) String() string {
+  if p == nil {
+    return "<nil>"
+  }
+  return fmt.Sprintf("CalculateArgs(%+v)", *p)
+}
+
+func (p *CalculateArgs) CompareTo(other interface{}) (int, bool) {
+  if other == nil {
+    return 1, true
+  }
+  data, ok := other.(*CalculateArgs)
+  if !ok {
+    return 0, false
+  }
+  if p.Logid != data.Logid {
+    if p.Logid < data.Logid {
+      return -1, true
+    }
+    return 1, true
+  }
+  if cmp, ok := p.W.CompareTo(data.W); !ok || cmp != 0 {
+    return cmp, ok
+  }
+  return 0, true
+}
+
+func (p *CalculateArgs) AttributeByFieldId(id int) interface{} {
+  switch id {
+  default:
+    return nil
+  case 1:
+    return p.Logid
+  case 2:
+    return p.W
+  }
+  return nil
+}
+
+func (p *CalculateArgs) TStructFields() TFieldContainer {
+  return NewTFieldContainer([]TField{
+    NewTField("logid", I32, 1),
+    NewTField("w", STRUCT, 2),
+  })
+}
+
+/**
+ * Attributes:
+ *  - Success
+ *  - Ouch
+ */
+type CalculateResult struct {
+  TStruct
+  Success int32             "success" // 0
+  Ouch    *InvalidOperation "ouch"    // 1
+}
+
+func NewCalculateResult() *CalculateResult {
+  output := &CalculateResult{
+    TStruct: NewTStruct("calculate_result", []TField{
+      NewTField("success", I32, 0),
+      NewTField("ouch", STRUCT, 1),
+    }),
+  }
+  {
+  }
+  return output
+}
+
+func (p *CalculateResult) Read(iprot TProtocol) (err TProtocolException) {
+  _, err = iprot.ReadStructBegin()
+  if err != nil {
+    return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+  }
+  for {
+    fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+    if fieldId < 0 {
+      fieldId = int16(p.FieldIdFromFieldName(fieldName))
+    } else if fieldName == "" {
+      fieldName = p.FieldNameFromFieldId(int(fieldId))
+    }
+    if fieldTypeId == GENERIC {
+      fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId()
+    }
+    if err != nil {
+      return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+    }
+    if fieldTypeId == STOP {
+      break
+    }
+    if fieldId == 0 || fieldName == "success" {
+      if fieldTypeId == I32 {
+        err = p.ReadField0(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField0(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else if fieldId == 1 || fieldName == "ouch" {
+      if fieldTypeId == STRUCT {
+        err = p.ReadField1(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField1(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else {
+      err = iprot.Skip(fieldTypeId)
+      if err != nil {
+        return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+      }
+    }
+    err = iprot.ReadFieldEnd()
+    if err != nil {
+      return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+    }
+  }
+  err = iprot.ReadStructEnd()
+  if err != nil {
+    return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *CalculateResult) ReadField0(iprot TProtocol) (err TProtocolException) {
+  v52, err53 := iprot.ReadI32()
+  if err53 != nil {
+    return NewTProtocolExceptionReadField(0, "success", p.ThriftName(), err53)
+  }
+  p.Success = v52
+  return err
+}
+
+func (p *CalculateResult) ReadFieldSuccess(iprot TProtocol) TProtocolException {
+  return p.ReadField0(iprot)
+}
+
+func (p *CalculateResult) ReadField1(iprot TProtocol) (err TProtocolException) {
+  p.Ouch = NewInvalidOperation()
+  err56 := p.Ouch.Read(iprot)
+  if err56 != nil {
+    return NewTProtocolExceptionReadStruct("p.OuchInvalidOperation", err56)
+  }
+  return err
+}
+
+func (p *CalculateResult) ReadFieldOuch(iprot TProtocol) TProtocolException {
+  return p.ReadField1(iprot)
+}
+
+func (p *CalculateResult) Write(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteStructBegin("calculate_result")
+  if err != nil {
+    return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+  }
+  err = p.WriteField0(oprot)
+  if err != nil {
+    return err
+  }
+  err = p.WriteField1(oprot)
+  if err != nil {
+    return err
+  }
+  err = oprot.WriteFieldStop()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err)
+  }
+  err = oprot.WriteStructEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *CalculateResult) WriteField0(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteFieldBegin("success", I32, 0)
+  if err != nil {
+    return NewTProtocolExceptionWriteField(0, "success", p.ThriftName(), err)
+  }
+  err = oprot.WriteI32(int32(p.Success))
+  if err != nil {
+    return NewTProtocolExceptionWriteField(0, "success", p.ThriftName(), err)
+  }
+  err = oprot.WriteFieldEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(0, "success", p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *CalculateResult) WriteFieldSuccess(oprot TProtocol) TProtocolException {
+  return p.WriteField0(oprot)
+}
+
+func (p *CalculateResult) WriteField1(oprot TProtocol) (err TProtocolException) {
+  if p.Ouch != nil {
+    err = oprot.WriteFieldBegin("ouch", STRUCT, 1)
+    if err != nil {
+      return NewTProtocolExceptionWriteField(1, "ouch", p.ThriftName(), err)
+    }
+    err = p.Ouch.Write(oprot)
+    if err != nil {
+      return NewTProtocolExceptionWriteStruct("InvalidOperation", err)
+    }
+    err = oprot.WriteFieldEnd()
+    if err != nil {
+      return NewTProtocolExceptionWriteField(1, "ouch", p.ThriftName(), err)
+    }
+  }
+  return err
+}
+
+func (p *CalculateResult) WriteFieldOuch(oprot TProtocol) TProtocolException {
+  return p.WriteField1(oprot)
+}
+
+func (p *CalculateResult) TStructName() string {
+  return "CalculateResult"
+}
+
+func (p *CalculateResult) ThriftName() string {
+  return "calculate_result"
+}
+
+func (p *CalculateResult) String() string {
+  if p == nil {
+    return "<nil>"
+  }
+  return fmt.Sprintf("CalculateResult(%+v)", *p)
+}
+
+func (p *CalculateResult) CompareTo(other interface{}) (int, bool) {
+  if other == nil {
+    return 1, true
+  }
+  data, ok := other.(*CalculateResult)
+  if !ok {
+    return 0, false
+  }
+  if p.Success != data.Success {
+    if p.Success < data.Success {
+      return -1, true
+    }
+    return 1, true
+  }
+  if cmp, ok := p.Ouch.CompareTo(data.Ouch); !ok || cmp != 0 {
+    return cmp, ok
+  }
+  return 0, true
+}
+
+func (p *CalculateResult) AttributeByFieldId(id int) interface{} {
+  switch id {
+  default:
+    return nil
+  case 0:
+    return p.Success
+  case 1:
+    return p.Ouch
+  }
+  return nil
+}
+
+func (p *CalculateResult) TStructFields() TFieldContainer {
+  return NewTFieldContainer([]TField{
+    NewTField("success", I32, 0),
+    NewTField("ouch", STRUCT, 1),
+  })
+}
+
+
+/**
+ * Structs can also be exceptions, if they are nasty.
+ * 
+ * Attributes:
+ *  - What
+ *  - Why
+ */
+type InvalidOperation struct {
+  TStruct
+  _    interface{} "what" // nil # 0
+  What int32       "what" // 1
+  Why  string      "why"  // 2
+}
+
+func NewInvalidOperation() *InvalidOperation {
+  output := &InvalidOperation{
+    TStruct: NewTStruct("InvalidOperation", []TField{
+      NewTField("what", I32, 1),
+      NewTField("why", STRING, 2),
+    }),
+  }
+  {
+  }
+  return output
+}
+
+func (p *InvalidOperation) Read(iprot TProtocol) (err TProtocolException) {
+  _, err = iprot.ReadStructBegin()
+  if err != nil {
+    return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+  }
+  for {
+    fieldName, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
+    if fieldId < 0 {
+      fieldId = int16(p.FieldIdFromFieldName(fieldName))
+    } else if fieldName == "" {
+      fieldName = p.FieldNameFromFieldId(int(fieldId))
+    }
+    if fieldTypeId == GENERIC {
+      fieldTypeId = p.FieldFromFieldId(int(fieldId)).TypeId()
+    }
+    if err != nil {
+      return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+    }
+    if fieldTypeId == STOP {
+      break
+    }
+    if fieldId == 1 || fieldName == "what" {
+      if fieldTypeId == I32 {
+        err = p.ReadField1(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField1(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else if fieldId == 2 || fieldName == "why" {
+      if fieldTypeId == STRING {
+        err = p.ReadField2(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else if fieldTypeId == VOID {
+        err = iprot.Skip(fieldTypeId)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      } else {
+        err = p.ReadField2(iprot)
+        if err != nil {
+          return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+        }
+      }
+    } else {
+      err = iprot.Skip(fieldTypeId)
+      if err != nil {
+        return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+      }
+    }
+    err = iprot.ReadFieldEnd()
+    if err != nil {
+      return NewTProtocolExceptionReadField(int(fieldId), fieldName, p.ThriftName(), err)
+    }
+  }
+  err = iprot.ReadStructEnd()
+  if err != nil {
+    return NewTProtocolExceptionReadStruct(p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *InvalidOperation) ReadField1(iprot TProtocol) (err TProtocolException) {
+  v12, err13 := iprot.ReadI32()
+  if err13 != nil {
+    return NewTProtocolExceptionReadField(1, "what", p.ThriftName(), err13)
+  }
+  p.What = v12
+  return err
+}
+
+func (p *InvalidOperation) ReadFieldWhat(iprot TProtocol) TProtocolException {
+  return p.ReadField1(iprot)
+}
+
+func (p *InvalidOperation) ReadField2(iprot TProtocol) (err TProtocolException) {
+  v14, err15 := iprot.ReadString()
+  if err15 != nil {
+    return NewTProtocolExceptionReadField(2, "why", p.ThriftName(), err15)
+  }
+  p.Why = v14
+  return err
+}
+
+func (p *InvalidOperation) ReadFieldWhy(iprot TProtocol) TProtocolException {
+  return p.ReadField2(iprot)
+}
+
+func (p *InvalidOperation) Write(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteStructBegin("InvalidOperation")
+  if err != nil {
+    return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+  }
+  err = p.WriteField1(oprot)
+  if err != nil {
+    return err
+  }
+  err = p.WriteField2(oprot)
+  if err != nil {
+    return err
+  }
+  err = oprot.WriteFieldStop()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(-1, "STOP", p.ThriftName(), err)
+  }
+  err = oprot.WriteStructEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteStruct(p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *InvalidOperation) WriteField1(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteFieldBegin("what", I32, 1)
+  if err != nil {
+    return NewTProtocolExceptionWriteField(1, "what", p.ThriftName(), err)
+  }
+  err = oprot.WriteI32(int32(p.What))
+  if err != nil {
+    return NewTProtocolExceptionWriteField(1, "what", p.ThriftName(), err)
+  }
+  err = oprot.WriteFieldEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(1, "what", p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *InvalidOperation) WriteFieldWhat(oprot TProtocol) TProtocolException {
+  return p.WriteField1(oprot)
+}
+
+func (p *InvalidOperation) WriteField2(oprot TProtocol) (err TProtocolException) {
+  err = oprot.WriteFieldBegin("why", STRING, 2)
+  if err != nil {
+    return NewTProtocolExceptionWriteField(2, "why", p.ThriftName(), err)
+  }
+  err = oprot.WriteString(string(p.Why))
+  if err != nil {
+    return NewTProtocolExceptionWriteField(2, "why", p.ThriftName(), err)
+  }
+  err = oprot.WriteFieldEnd()
+  if err != nil {
+    return NewTProtocolExceptionWriteField(2, "why", p.ThriftName(), err)
+  }
+  return err
+}
+
+func (p *InvalidOperation) WriteFieldWhy(oprot TProtocol) TProtocolException {
+  return p.WriteField2(oprot)
+}
+
+func (p *InvalidOperation) TStructName() string {
+  return "InvalidOperation"
+}
+
+func (p *InvalidOperation) ThriftName() string {
+  return "InvalidOperation"
+}
+
+func (p *InvalidOperation) String() string {
+  if p == nil {
+    return "<nil>"
+  }
+  return fmt.Sprintf("InvalidOperation(%+v)", *p)
+}
+
+func (p *InvalidOperation) CompareTo(other interface{}) (int, bool) {
+  if other == nil {
+    return 1, true
+  }
+  data, ok := other.(*InvalidOperation)
+  if !ok {
+    return 0, false
+  }
+  if p.What != data.What {
+    if p.What < data.What {
+      return -1, true
+    }
+    return 1, true
+  }
+  if p.Why != data.Why {
+    if p.Why < data.Why {
+      return -1, true
+    }
+    return 1, true
+  }
+  return 0, true
+}
+
+func (p *InvalidOperation) AttributeByFieldId(id int) interface{} {
+  switch id {
+  default:
+    return nil
+  case 1:
+    return p.What
+  case 2:
+    return p.Why
+  }
+  return nil
+}
+
+func (p *InvalidOperation) TStructFields() TFieldContainer {
+  return NewTFieldContainer([]TField{
+    NewTField("what", I32, 1),
+    NewTField("why", STRING, 2),
+  })
+}
diff --git a/lib/go/thrift/tserver.go b/lib/go/thrift/tserver.go
new file mode 100644
index 0000000..6bc3167
--- /dev/null
+++ b/lib/go/thrift/tserver.go
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "os"
+)
+
+type TServer interface {
+  /**
+   * Core processor
+   */
+  ProcessorFactory() TProcessorFactory
+  /**
+   * Server transport
+   */
+  ServerTransport() TServerTransport
+  /**
+   * Input Transport Factory
+   */
+  InputTransportFactory() TTransportFactory
+  /**
+   * Output Transport Factory
+   */
+  OutputTransportFactory() TTransportFactory
+  /**
+   * Input Protocol Factory
+   */
+  InputProtocolFactory() TProtocolFactory
+  /**
+   * Output Protocol Factory
+   */
+  OutputProtocolFactory() TProtocolFactory
+
+  /**
+   * The run method fires up the server and gets things going.
+   */
+  Serve() os.Error
+  /**
+   * Stop the server. This is optional on a per-implementation basis. Not
+   * all servers are required to be cleanly stoppable.
+   */
+  Stop() os.Error
+}
diff --git a/lib/go/thrift/tserver_socket.go b/lib/go/thrift/tserver_socket.go
new file mode 100644
index 0000000..dc3e748
--- /dev/null
+++ b/lib/go/thrift/tserver_socket.go
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "net"
+  "os"
+)
+
+
+type TServerSocket struct {
+  /**
+   * Underlying socket conection object
+   */
+  conn net.Conn
+  /**
+   * Underlying socket conection object
+   */
+  listener net.Listener
+
+  /**
+   * Address to listen on
+   */
+  addr net.Addr
+
+  /**
+   * Client timeout in nanoseconds
+   */
+  nsecClientTimeout int64
+}
+
+type TServerSocketTransportFactory struct {
+  addr              net.Addr
+  nsecClientTimeout int64
+}
+
+func (p *TServerSocketTransportFactory) GetTransport(trans TTransport) TTransport {
+  if trans != nil {
+    t, ok := trans.(*TServerSocket)
+    if ok && t.addr != nil {
+      s, _ := NewTServerSocketAddrTimeout(t.addr, t.nsecClientTimeout)
+      return s
+    }
+  }
+  s, _ := NewTServerSocketAddrTimeout(p.addr, p.nsecClientTimeout)
+  return s
+}
+
+func NewTServerSocketTransportFactory(addr net.Addr, nsecClientTimeout int64) *TServerSocketTransportFactory {
+  return &TServerSocketTransportFactory{addr: addr, nsecClientTimeout: nsecClientTimeout}
+}
+
+func NewTServerSocketConn(conn net.Conn) *TServerSocket {
+  return NewTServerSocketConnTimeout(conn, 0)
+}
+
+func NewTServerSocketConnTimeout(conn net.Conn, nsecClientTimeout int64) *TServerSocket {
+  v := &TServerSocket{conn: conn, addr: conn.LocalAddr(), nsecClientTimeout: nsecClientTimeout}
+  conn.SetTimeout(nsecClientTimeout)
+  return v
+}
+
+func NewTServerSocketAddr(addr net.Addr) (*TServerSocket, TTransportException) {
+  return NewTServerSocketAddrTimeout(addr, 0)
+}
+
+func NewTServerSocketAddrTimeout(addr net.Addr, nsecClientTimeout int64) (*TServerSocket, TTransportException) {
+  s := &TServerSocket{addr: addr, nsecClientTimeout: nsecClientTimeout}
+  return s, nil
+}
+
+func (p *TServerSocket) Listen() (err os.Error) {
+  if p.listener == nil {
+    if p.listener, err = net.Listen("tcp", p.addr.String()); err != nil {
+      return err
+    }
+  }
+  return nil
+}
+
+func (p *TServerSocket) Accept() (TTransport, os.Error) {
+  if p.listener == nil {
+    if err := p.Listen(); err != nil {
+      return nil, NewTTransportExceptionFromOsError(err)
+    }
+    if p.listener == nil {
+      return nil, NewTTransportException(NOT_OPEN, "No underlying server socket")
+    }
+  }
+  conn, err := p.listener.Accept()
+  if err != nil {
+    return nil, NewTTransportExceptionFromOsError(err)
+  }
+  conn.SetTimeout(p.nsecClientTimeout)
+  return NewTSocketConn(conn)
+}
+
+/**
+ * Checks whether the socket is connected.
+ */
+func (p *TServerSocket) IsOpen() bool {
+  return p.listener != nil
+}
+
+/**
+ * Connects the socket, creating a new socket object if necessary.
+ */
+func (p *TServerSocket) Open() os.Error {
+  if !p.IsOpen() {
+    l, err := net.Listen(p.addr.Network(), p.addr.String())
+    if err != nil {
+      return err
+    }
+    p.listener = l
+    return nil
+  }
+  return NewTTransportException(ALREADY_OPEN, "Server socket already open")
+}
+
+/**
+ * Perform a nonblocking read into buffer.
+ */
+func (p *TServerSocket) Read(buf []byte) (int, os.Error) {
+  return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Read([]byte) is not implemented")
+}
+
+func (p *TServerSocket) ReadAll(buf []byte) (int, os.Error) {
+  return ReadAllTransport(p, buf)
+}
+
+/**
+ * Perform a nonblocking write of the data in buffer;
+ */
+func (p *TServerSocket) Write(buf []byte) (int, os.Error) {
+  return 0, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Write([]byte) is not implemented")
+}
+
+/**
+ * Flushes the underlying output stream if not null.
+ */
+func (p *TServerSocket) Flush() os.Error {
+  return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "TServerSocket.Flush() is not implemented")
+}
+
+func (p *TServerSocket) Addr() net.Addr {
+  return p.addr
+}
+
+func (p *TServerSocket) Peek() bool {
+  return p.IsOpen()
+}
+
+/**
+ * Closes the socket.
+ */
+func (p *TServerSocket) Close() (err os.Error) {
+  if p.IsOpen() {
+    err := p.listener.Close()
+    if err != nil {
+      return NewTTransportExceptionFromOsError(err)
+    }
+    p.listener = nil
+  }
+  if p.conn != nil {
+    err := p.conn.Close()
+    if err != nil {
+      return NewTTransportExceptionFromOsError(err)
+    }
+    p.conn = nil
+  }
+  return nil
+}
+
+func (p *TServerSocket) Interrupt() os.Error {
+  // TODO(pomack) fix Interrupt as it is probably not right
+  return NewTTransportExceptionFromOsError(p.Close())
+}
diff --git a/lib/go/thrift/tserver_test.go b/lib/go/thrift/tserver_test.go
new file mode 100644
index 0000000..3cbe879
--- /dev/null
+++ b/lib/go/thrift/tserver_test.go
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  "testing"
+)
+
+func TestNothing(t *testing.T) {
+
+}
diff --git a/lib/go/thrift/tserver_transport.go b/lib/go/thrift/tserver_transport.go
new file mode 100644
index 0000000..ef3a462
--- /dev/null
+++ b/lib/go/thrift/tserver_transport.go
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import "os"
+
+/**
+ * Server transport. Object which provides client transports.
+ *
+ */
+type TServerTransport interface {
+  Listen() os.Error
+  Accept() (TTransport, os.Error)
+  Close() os.Error
+
+  /**
+   * Optional method implementation. This signals to the server transport
+   * that it should break out of any accept() or listen() that it is currently
+   * blocked on. This method, if implemented, MUST be thread safe, as it may
+   * be called from a different thread context than the other TServerTransport
+   * methods.
+   */
+  Interrupt() os.Error
+}
diff --git a/lib/go/thrift/tset.go b/lib/go/thrift/tset.go
new file mode 100644
index 0000000..f868109
--- /dev/null
+++ b/lib/go/thrift/tset.go
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "container/list"
+)
+
+/**
+ * Helper class that encapsulates set metadata.
+ *
+ */
+type TSet interface {
+  TContainer
+  ElemType() TType
+  Add(data interface{})
+  Remove(data interface{})
+  Less(other interface{}) bool
+  Front() *list.Element
+  Back() *list.Element
+  Values() []interface{}
+}
+
+type tSet struct {
+  elemType TType
+  size     int
+  l        *list.List
+}
+
+func NewTSet(t TType, s int) TSet {
+  return &tSet{elemType: t, size: s, l: list.New()}
+}
+
+func NewTSetDefault() TSet {
+  return NewTSet(STOP, 0)
+}
+
+func (p *tSet) ElemType() TType {
+  return p.elemType
+}
+
+func (p *tSet) Front() *list.Element {
+  return p.l.Front()
+}
+
+func (p *tSet) Back() *list.Element {
+  return p.l.Back()
+}
+
+func (p *tSet) Len() int {
+  if p.l.Len() != 0 {
+    return p.l.Len()
+  }
+  return p.size
+}
+
+func (p *tSet) Contains(data interface{}) bool {
+  return p.find(data) != nil
+}
+
+func (p *tSet) Add(other interface{}) {
+  if data, ok := p.elemType.CoerceData(other); ok {
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      if cmp, ok := p.elemType.Compare(data, elem.Value); ok && cmp >= 0 {
+        if cmp > 0 {
+          p.l.InsertBefore(data, elem)
+        }
+        return
+      }
+    }
+  }
+}
+
+func (p *tSet) Remove(data interface{}) {
+  elem := p.find(data)
+  if elem != nil {
+    p.l.Remove(elem)
+  }
+}
+
+func (p *tSet) Less(other interface{}) bool {
+  cmp, ok := p.CompareTo(other)
+  return ok && cmp > 0
+}
+
+func (p *tSet) Equals(other interface{}) bool {
+  c, cok := p.CompareTo(other)
+  return cok && c == 0
+}
+
+func (p *tSet) CompareTo(other interface{}) (int, bool) {
+  return TType(SET).Compare(p, other)
+}
+
+func (p *tSet) find(data interface{}) *list.Element {
+  if data == nil {
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      if elem.Value == nil {
+        return elem
+      }
+    }
+    return nil
+  }
+  data, ok := p.elemType.CoerceData(data)
+  if data == nil || !ok {
+    return nil
+  }
+  if p.elemType.IsBaseType() || p.elemType.IsEnum() {
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      if data == elem.Value {
+        return elem
+      }
+    }
+    return nil
+  }
+  if cmp, ok := data.(EqualsOtherInterface); ok {
+    for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+      if cmp.Equals(elem.Value) {
+        return elem
+      }
+    }
+    return nil
+  }
+  switch p.elemType {
+  case MAP:
+    if cmp, ok := data.(EqualsMap); ok {
+      for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+        v := elem.Value
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TMap)) {
+          return elem
+        }
+      }
+      return nil
+    }
+  case SET:
+    if cmp, ok := data.(EqualsSet); ok {
+      for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+        v := elem.Value
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TSet)) {
+          return elem
+        }
+      }
+      return nil
+    }
+  case LIST:
+    if cmp, ok := data.(EqualsList); ok {
+      for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+        v := elem.Value
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TList)) {
+          return elem
+        }
+      }
+      return nil
+    }
+  case STRUCT:
+    if cmp, ok := data.(EqualsStruct); ok {
+      for elem := p.l.Front(); elem != nil; elem = elem.Next() {
+        v := elem.Value
+        if v == nil {
+          continue
+        }
+        if cmp.Equals(v.(TStruct)) {
+          return elem
+        }
+      }
+      return nil
+    }
+  }
+  return nil
+}
+
+func (p *tSet) Values() []interface{} {
+  size := p.l.Len()
+  values := make([]interface{}, size, size)
+  i := 0
+  for v := p.l.Front(); v != nil; v = v.Next() {
+    values[i] = v.Value
+    i++
+  }
+  return values
+}
diff --git a/lib/go/thrift/tsimple_json_protocol.go b/lib/go/thrift/tsimple_json_protocol.go
new file mode 100644
index 0000000..569dd9c
--- /dev/null
+++ b/lib/go/thrift/tsimple_json_protocol.go
@@ -0,0 +1,1281 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "bufio"
+  "bytes"
+  "container/vector"
+  "encoding/base64"
+  "fmt"
+  "io"
+  "json"
+  "math"
+  "os"
+  "strconv"
+  "strings"
+)
+
+type _ParseContext int
+
+const (
+  _CONTEXT_IN_TOPLEVEL          _ParseContext = 1
+  _CONTEXT_IN_LIST_FIRST        _ParseContext = 2
+  _CONTEXT_IN_LIST              _ParseContext = 3
+  _CONTEXT_IN_OBJECT_FIRST      _ParseContext = 4
+  _CONTEXT_IN_OBJECT_NEXT_KEY   _ParseContext = 5
+  _CONTEXT_IN_OBJECT_NEXT_VALUE _ParseContext = 6
+)
+
+func (p _ParseContext) String() string {
+  switch p {
+  case _CONTEXT_IN_TOPLEVEL:
+    return "TOPLEVEL"
+  case _CONTEXT_IN_LIST_FIRST:
+    return "LIST-FIRST"
+  case _CONTEXT_IN_LIST:
+    return "LIST"
+  case _CONTEXT_IN_OBJECT_FIRST:
+    return "OBJECT-FIRST"
+  case _CONTEXT_IN_OBJECT_NEXT_KEY:
+    return "OBJECT-NEXT-KEY"
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    return "OBJECT-NEXT-VALUE"
+  }
+  return "UNKNOWN-PARSE-CONTEXT"
+}
+
+/**
+ * JSON protocol implementation for thrift.
+ *
+ * This protocol produces/consumes a simple output format
+ * suitable for parsing by scripting languages.  It should not be
+ * confused with the full-featured TJSONProtocol.
+ *
+ */
+type TSimpleJSONProtocol struct {
+  //TProtocolBase;
+  trans TTransport
+
+  /**
+   * Stack of nested contexts that we may be in.
+   */
+  parseContextStack vector.IntVector
+  /**
+   * Stack of nested contexts that we may be in.
+   */
+  dumpContext vector.IntVector
+
+  /**
+   * Current context that we are in
+   */
+  writer TTransport
+  reader *bufio.Reader
+}
+
+/**
+ * Constructor
+ */
+func NewTSimpleJSONProtocol(t TTransport) *TSimpleJSONProtocol {
+  v := &TSimpleJSONProtocol{trans: t,
+    writer: t,
+    reader: bufio.NewReader(t),
+  }
+  v.parseContextStack.Push(int(_CONTEXT_IN_TOPLEVEL))
+  v.dumpContext.Push(int(_CONTEXT_IN_TOPLEVEL))
+  return v
+}
+
+/**
+ * Factory
+ */
+type TSimpleJSONProtocolFactory struct{}
+
+func (p *TSimpleJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol {
+  return NewTSimpleJSONProtocol(trans)
+}
+
+func NewTSimpleJSONProtocolFactory() *TSimpleJSONProtocolFactory {
+  return &TSimpleJSONProtocolFactory{}
+}
+
+var (
+  JSON_COMMA                   []byte
+  JSON_COLON                   []byte
+  JSON_LBRACE                  []byte
+  JSON_RBRACE                  []byte
+  JSON_LBRACKET                []byte
+  JSON_RBRACKET                []byte
+  JSON_QUOTE                   byte
+  JSON_QUOTE_BYTES             []byte
+  JSON_NULL                    []byte
+  JSON_TRUE                    []byte
+  JSON_FALSE                   []byte
+  JSON_INFINITY                string
+  JSON_NEGATIVE_INFINITY       string
+  JSON_NAN                     string
+  JSON_INFINITY_BYTES          []byte
+  JSON_NEGATIVE_INFINITY_BYTES []byte
+  JSON_NAN_BYTES               []byte
+  json_nonbase_map_elem_bytes  []byte
+)
+
+func init() {
+  JSON_COMMA = []byte{','}
+  JSON_COLON = []byte{':'}
+  JSON_LBRACE = []byte{'{'}
+  JSON_RBRACE = []byte{'}'}
+  JSON_LBRACKET = []byte{'['}
+  JSON_RBRACKET = []byte{']'}
+  JSON_QUOTE = '"'
+  JSON_QUOTE_BYTES = []byte{'"'}
+  JSON_NULL = []byte{'n', 'u', 'l', 'l'}
+  JSON_TRUE = []byte{'t', 'r', 'u', 'e'}
+  JSON_FALSE = []byte{'f', 'a', 'l', 's', 'e'}
+  JSON_INFINITY = "Infinity"
+  JSON_NEGATIVE_INFINITY = "-Infinity"
+  JSON_NAN = "NaN"
+  JSON_INFINITY_BYTES = []byte{'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'}
+  JSON_NEGATIVE_INFINITY_BYTES = []byte{'-', 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'}
+  JSON_NAN_BYTES = []byte{'N', 'a', 'N'}
+  json_nonbase_map_elem_bytes = []byte{']', ',', '['}
+}
+
+func JsonQuote(s string) string {
+  b, _ := json.Marshal(s)
+  s1 := string(b)
+  return s1
+}
+
+func JsonUnquote(s string) (string, bool) {
+  s1 := new(string)
+  err := json.Unmarshal([]byte(s), s1)
+  return *s1, err == nil
+}
+
+
+func (p *TSimpleJSONProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) TProtocolException {
+  if e := p.OutputListBegin(); e != nil {
+    return e
+  }
+  if e := p.WriteString(name); e != nil {
+    return e
+  }
+  if e := p.WriteByte(byte(typeId)); e != nil {
+    return e
+  }
+  if e := p.WriteI32(seqId); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) WriteMessageEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteStructBegin(name string) TProtocolException {
+  if e := p.OutputObjectBegin(); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) WriteStructEnd() TProtocolException {
+  return p.OutputObjectEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteFieldBegin(name string, typeId TType, id int16) TProtocolException {
+  if e := p.WriteString(name); e != nil {
+    return e
+  }
+  return nil
+  /*
+    	if e := p.OutputListBegin(); e != nil {
+        return e
+      }
+      if e := p.WriteByte(byte(typeId)); e != nil {
+        return e
+      }
+      return p.WriteI16(id)
+  */
+}
+
+func (p *TSimpleJSONProtocol) WriteFieldEnd() TProtocolException {
+  //return p.OutputListEnd()
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) WriteFieldStop() TProtocolException { return nil }
+
+func (p *TSimpleJSONProtocol) WriteMapBegin(keyType TType, valueType TType, size int) TProtocolException {
+  if e := p.OutputListBegin(); e != nil {
+    return e
+  }
+  if e := p.WriteByte(byte(keyType)); e != nil {
+    return e
+  }
+  if e := p.WriteByte(byte(valueType)); e != nil {
+    return e
+  }
+  return p.WriteI32(int32(size))
+}
+
+func (p *TSimpleJSONProtocol) WriteMapEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteListBegin(elemType TType, size int) TProtocolException {
+  return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TSimpleJSONProtocol) WriteListEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteSetBegin(elemType TType, size int) TProtocolException {
+  return p.OutputElemListBegin(elemType, size)
+}
+
+func (p *TSimpleJSONProtocol) WriteSetEnd() TProtocolException {
+  return p.OutputListEnd()
+}
+
+func (p *TSimpleJSONProtocol) WriteBool(b bool) TProtocolException {
+  return p.OutputBool(b)
+}
+
+func (p *TSimpleJSONProtocol) WriteByte(b byte) TProtocolException {
+  return p.WriteI32(int32(b))
+}
+
+func (p *TSimpleJSONProtocol) WriteI16(v int16) TProtocolException {
+  return p.WriteI32(int32(v))
+}
+
+func (p *TSimpleJSONProtocol) WriteI32(v int32) TProtocolException {
+  return p.OutputI64(int64(v))
+}
+
+func (p *TSimpleJSONProtocol) WriteI64(v int64) TProtocolException {
+  return p.OutputI64(int64(v))
+}
+
+func (p *TSimpleJSONProtocol) WriteDouble(v float64) TProtocolException {
+  return p.OutputF64(v)
+}
+
+func (p *TSimpleJSONProtocol) WriteString(v string) TProtocolException {
+  return p.OutputString(v)
+}
+
+func (p *TSimpleJSONProtocol) WriteBinary(v []byte) TProtocolException {
+  // JSON library only takes in a string, 
+  // not an arbitrary byte array, to ensure bytes are transmitted
+  // efficiently we must convert this into a valid JSON string
+  // therefore we use base64 encoding to avoid excessive escaping/quoting
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  writer := base64.NewEncoder(base64.StdEncoding, p.writer)
+  if _, e := writer.Write(v); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  if e := writer.Close(); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  if _, e := p.writer.Write(JSON_QUOTE_BYTES); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  return p.OutputPostValue()
+}
+
+/**
+ * Reading methods.
+ */
+
+func (p *TSimpleJSONProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err TProtocolException) {
+  if isNull, err := p.ParseListBegin(); isNull || err != nil {
+    return name, typeId, seqId, err
+  }
+  if name, err = p.ReadString(); err != nil {
+    return name, typeId, seqId, err
+  }
+  bTypeId, err := p.ReadByte()
+  typeId = TMessageType(bTypeId)
+  if err != nil {
+    return name, typeId, seqId, err
+  }
+  if seqId, err = p.ReadI32(); err != nil {
+    return name, typeId, seqId, err
+  }
+  return name, typeId, seqId, nil
+}
+
+func (p *TSimpleJSONProtocol) ReadMessageEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadStructBegin() (name string, err TProtocolException) {
+  _, err = p.ParseObjectStart()
+  return "", err
+}
+
+func (p *TSimpleJSONProtocol) ReadStructEnd() TProtocolException {
+  return p.ParseObjectEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadFieldBegin() (string, TType, int16, TProtocolException) {
+  if err := p.ParsePreValue(); err != nil {
+    return "", STOP, 0, err
+  }
+  if p.reader.Buffered() < 1 {
+    return "", STOP, 0, nil
+  }
+  b, _ := p.reader.Peek(1)
+  if len(b) > 0 {
+    switch b[0] {
+    case JSON_RBRACE[0]:
+      return "", STOP, 0, nil
+    case JSON_QUOTE:
+      p.reader.ReadByte()
+      name, err := p.ParseStringBody()
+      if err != nil {
+        return name, STOP, 0, err
+      }
+      return name, GENERIC, -1, p.ParsePostValue()
+      /*
+         if err = p.ParsePostValue(); err != nil {
+           return name, STOP, 0, err
+         }
+         if isNull, err := p.ParseListBegin(); isNull || err != nil {
+           return name, STOP, 0, err
+         }
+         bType, err := p.ReadByte()
+         thetype := TType(bType)
+         if err != nil {
+           return name, thetype, 0, err
+         }
+         id, err := p.ReadI16()
+         return name, thetype, id, err
+      */
+    }
+    return "", STOP, 0, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \"}\" or '\"', but found: '", string(b), "'"))
+  }
+  return "", STOP, 0, NewTProtocolExceptionFromOsError(os.EOF)
+}
+
+func (p *TSimpleJSONProtocol) ReadFieldEnd() TProtocolException {
+  return nil
+  //return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, e TProtocolException) {
+  if isNull, e := p.ParseListBegin(); isNull || e != nil {
+    return VOID, VOID, 0, e
+  }
+
+  // read keyType
+  bKeyType, e := p.ReadByte()
+  keyType = TType(bKeyType)
+  if e != nil {
+    return keyType, valueType, size, e
+  }
+
+  // read valueType
+  bValueType, e := p.ReadByte()
+  valueType = TType(bValueType)
+  if e != nil {
+    return keyType, valueType, size, e
+  }
+
+  // read size
+  iSize, err := p.ReadI64()
+  size = int(iSize)
+  return keyType, valueType, size, err
+}
+
+func (p *TSimpleJSONProtocol) ReadMapEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadListBegin() (elemType TType, size int, e TProtocolException) {
+  return p.ParseElemListBegin()
+}
+
+func (p *TSimpleJSONProtocol) ReadListEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadSetBegin() (elemType TType, size int, e TProtocolException) {
+  return p.ParseElemListBegin()
+}
+
+func (p *TSimpleJSONProtocol) ReadSetEnd() TProtocolException {
+  return p.ParseListEnd()
+}
+
+func (p *TSimpleJSONProtocol) ReadBool() (bool, TProtocolException) {
+  var value bool
+  if err := p.ParsePreValue(); err != nil {
+    return value, err
+  }
+  b, _ := p.reader.Peek(len(JSON_FALSE))
+  if len(b) > 0 {
+    switch b[0] {
+    case JSON_TRUE[0]:
+      if string(b[0:len(JSON_TRUE)]) == string(JSON_TRUE) {
+        p.reader.Read(b[0:len(JSON_TRUE)])
+        value = true
+      } else {
+        return value, NewTProtocolException(INVALID_DATA, "Expected \"true\" but found: "+string(b))
+      }
+      break
+    case JSON_FALSE[0]:
+      if string(b[0:len(JSON_FALSE)]) == string(JSON_FALSE) {
+        p.reader.Read(b[0:len(JSON_FALSE)])
+        value = false
+      } else {
+        return value, NewTProtocolException(INVALID_DATA, "Expected \"false\" but found: "+string(b))
+      }
+      break
+    case JSON_NULL[0]:
+      if string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+        p.reader.Read(b[0:len(JSON_NULL)])
+        value = false
+      } else {
+        return value, NewTProtocolException(INVALID_DATA, "Expected \"null\" but found: "+string(b))
+      }
+    default:
+      return value, NewTProtocolException(INVALID_DATA, "Expected \"true\", \"false\", or \"null\" but found: "+string(b))
+    }
+  }
+  return value, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ReadByte() (byte, TProtocolException) {
+  v, err := p.ReadI64()
+  return byte(v), err
+}
+
+func (p *TSimpleJSONProtocol) ReadI16() (int16, TProtocolException) {
+  v, err := p.ReadI64()
+  return int16(v), err
+}
+
+func (p *TSimpleJSONProtocol) ReadI32() (int32, TProtocolException) {
+  v, err := p.ReadI64()
+  return int32(v), err
+}
+
+func (p *TSimpleJSONProtocol) ReadI64() (int64, TProtocolException) {
+  v, _, err := p.ParseI64()
+  return v, err
+}
+
+func (p *TSimpleJSONProtocol) ReadDouble() (float64, TProtocolException) {
+  v, _, err := p.ParseF64()
+  return v, err
+}
+
+func (p *TSimpleJSONProtocol) ReadString() (string, TProtocolException) {
+  var v string
+  if err := p.ParsePreValue(); err != nil {
+    return v, err
+  }
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) > 0 && b[0] == JSON_QUOTE {
+    p.reader.ReadByte()
+    value, err := p.ParseStringBody()
+    v = value
+    if err != nil {
+      return v, err
+    }
+  } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+    _, err := p.reader.Read(b[0:len(JSON_NULL)])
+    if err != nil {
+      return v, NewTProtocolExceptionFromOsError(err)
+    }
+  } else {
+    return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b)))
+  }
+  return v, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ReadBinary() ([]byte, TProtocolException) {
+  var v []byte
+  if err := p.ParsePreValue(); err != nil {
+    return nil, err
+  }
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) > 0 && b[0] == JSON_QUOTE {
+    p.reader.ReadByte()
+    value, err := p.ParseBase64EncodedBody()
+    v = value
+    if err != nil {
+      return v, err
+    }
+  } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+    _, err := p.reader.Read(b[0:len(JSON_NULL)])
+    if err != nil {
+      return v, NewTProtocolExceptionFromOsError(err)
+    }
+  } else {
+    return v, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected a JSON string, found ", string(b)))
+  }
+  return v, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) Flush() (err TProtocolException) {
+  return NewTProtocolExceptionFromOsError(p.writer.Flush())
+}
+
+func (p *TSimpleJSONProtocol) Skip(fieldType TType) (err TProtocolException) {
+  return SkipDefaultDepth(p, fieldType)
+}
+
+func (p *TSimpleJSONProtocol) Transport() TTransport {
+  return p.trans
+}
+
+
+func (p *TSimpleJSONProtocol) OutputPreValue() TProtocolException {
+  cxt := _ParseContext(p.dumpContext.Last())
+  switch cxt {
+  case _CONTEXT_IN_LIST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+    if _, e := p.writer.Write(JSON_COMMA); e != nil {
+      return NewTProtocolExceptionFromOsError(e)
+    }
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    if _, e := p.writer.Write(JSON_COLON); e != nil {
+      return NewTProtocolExceptionFromOsError(e)
+    }
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputPostValue() TProtocolException {
+  cxt := _ParseContext(p.dumpContext.Last())
+  switch cxt {
+  case _CONTEXT_IN_LIST_FIRST:
+    p.dumpContext.Pop()
+    p.dumpContext.Push(int(_CONTEXT_IN_LIST))
+    break
+  case _CONTEXT_IN_OBJECT_FIRST:
+    p.dumpContext.Pop()
+    p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_NEXT_VALUE))
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_KEY:
+    p.dumpContext.Pop()
+    p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_NEXT_VALUE))
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    p.dumpContext.Pop()
+    p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_NEXT_KEY))
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputBool(value bool) TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  var v string
+  if value {
+    v = string(JSON_TRUE)
+  } else {
+    v = string(JSON_FALSE)
+  }
+  switch _ParseContext(p.dumpContext.Last()) {
+  case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+    v = JsonQuote(v)
+  default:
+  }
+  if e := p.OutputStringData(v); e != nil {
+    return e
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputNull() TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  if _, e := p.writer.Write(JSON_NULL); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputF64(value float64) TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  var v string
+  if math.IsNaN(value) {
+    v = string(JSON_QUOTE) + JSON_NAN + string(JSON_QUOTE)
+  } else if math.IsInf(value, 1) {
+    v = string(JSON_QUOTE) + JSON_INFINITY + string(JSON_QUOTE)
+  } else if math.IsInf(value, -1) {
+    v = string(JSON_QUOTE) + JSON_NEGATIVE_INFINITY + string(JSON_QUOTE)
+  } else {
+    v = strconv.Ftoa64(value, 'g', -1)
+    switch _ParseContext(p.dumpContext.Last()) {
+    case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+      v = string(JSON_QUOTE) + v + string(JSON_QUOTE)
+    default:
+    }
+  }
+  if e := p.OutputStringData(v); e != nil {
+    return e
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputI64(value int64) TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  v := strconv.Itoa64(value)
+  switch _ParseContext(p.dumpContext.Last()) {
+  case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+    v = JsonQuote(v)
+  default:
+  }
+  if e := p.OutputStringData(v); e != nil {
+    return e
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputString(s string) TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  if e := p.OutputStringData(JsonQuote(s)); e != nil {
+    return e
+  }
+  return p.OutputPostValue()
+}
+
+func (p *TSimpleJSONProtocol) OutputStringData(s string) TProtocolException {
+  _, e := io.Copyn(p.writer, strings.NewReader(s), int64(len(s)))
+  return NewTProtocolExceptionFromOsError(e)
+}
+
+func (p *TSimpleJSONProtocol) OutputObjectBegin() TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  if _, e := p.writer.Write(JSON_LBRACE); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  p.dumpContext.Push(int(_CONTEXT_IN_OBJECT_FIRST))
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputObjectEnd() TProtocolException {
+  if _, e := p.writer.Write(JSON_RBRACE); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  p.dumpContext.Pop()
+  if e := p.OutputPostValue(); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputListBegin() TProtocolException {
+  if e := p.OutputPreValue(); e != nil {
+    return e
+  }
+  if _, e := p.writer.Write(JSON_LBRACKET); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  p.dumpContext.Push(int(_CONTEXT_IN_LIST_FIRST))
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputListEnd() TProtocolException {
+  if _, e := p.writer.Write(JSON_RBRACKET); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  p.dumpContext.Pop()
+  if e := p.OutputPostValue(); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) OutputElemListBegin(elemType TType, size int) TProtocolException {
+  if e := p.OutputListBegin(); e != nil {
+    return e
+  }
+  if e := p.WriteByte(byte(elemType)); e != nil {
+    return e
+  }
+  if e := p.WriteI64(int64(size)); e != nil {
+    return e
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) ParsePreValue() TProtocolException {
+  if e := p.readNonSignificantWhitespace(); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  cxt := _ParseContext(p.parseContextStack.Last())
+  if p.reader.Buffered() < 1 {
+    return nil
+  }
+  b, _ := p.reader.Peek(1)
+  switch cxt {
+  case _CONTEXT_IN_LIST:
+    if len(b) > 0 {
+      switch b[0] {
+      case JSON_RBRACKET[0]:
+        return nil
+      case JSON_COMMA[0]:
+        p.reader.ReadByte()
+        if e := p.readNonSignificantWhitespace(); e != nil {
+          return NewTProtocolExceptionFromOsError(e)
+        }
+        return nil
+      default:
+        return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \"]\" or \",\" in list context, but found \"", string(b), "\""))
+      }
+    }
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_KEY:
+    if len(b) > 0 {
+      switch b[0] {
+      case JSON_RBRACE[0]:
+        return nil
+      case JSON_COMMA[0]:
+        p.reader.ReadByte()
+        if e := p.readNonSignificantWhitespace(); e != nil {
+          return NewTProtocolExceptionFromOsError(e)
+        }
+        return nil
+      default:
+        return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \"}\" or \",\" in object context, but found \"", string(b), "\""))
+      }
+    }
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    if len(b) > 0 {
+      switch b[0] {
+      case JSON_COLON[0]:
+        p.reader.ReadByte()
+        if e := p.readNonSignificantWhitespace(); e != nil {
+          return NewTProtocolExceptionFromOsError(e)
+        }
+        return nil
+      default:
+        return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected \":\" in object context, but found \"", string(b), "\""))
+      }
+    }
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) ParsePostValue() TProtocolException {
+  if e := p.readNonSignificantWhitespace(); e != nil {
+    return NewTProtocolExceptionFromOsError(e)
+  }
+  cxt := _ParseContext(p.parseContextStack.Last())
+  switch cxt {
+  case _CONTEXT_IN_LIST_FIRST:
+    p.parseContextStack.Pop()
+    p.parseContextStack.Push(int(_CONTEXT_IN_LIST))
+    break
+  case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY:
+    p.parseContextStack.Pop()
+    p.parseContextStack.Push(int(_CONTEXT_IN_OBJECT_NEXT_VALUE))
+    break
+  case _CONTEXT_IN_OBJECT_NEXT_VALUE:
+    p.parseContextStack.Pop()
+    p.parseContextStack.Push(int(_CONTEXT_IN_OBJECT_NEXT_KEY))
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) readNonSignificantWhitespace() os.Error {
+  for p.reader.Buffered() > 0 {
+    b, _ := p.reader.Peek(1)
+    if len(b) < 1 {
+      return nil
+    }
+    switch b[0] {
+    case ' ', '\r', '\n', '\t':
+      p.reader.ReadByte()
+      continue
+    default:
+      break
+    }
+    break
+  }
+  return nil
+}
+
+func (p *TSimpleJSONProtocol) ParseStringBody() (string, TProtocolException) {
+  line, err := p.reader.ReadString(JSON_QUOTE)
+  if err != nil {
+    return "", NewTProtocolExceptionFromOsError(err)
+  }
+  l := len(line)
+  // count number of escapes to see if we need to keep going
+  i := 1
+  for ; i < l; i++ {
+    if line[l-i-1] != '\\' {
+      break
+    }
+  }
+  if i&0x01 == 1 {
+    v, ok := JsonUnquote(string(JSON_QUOTE) + line)
+    if !ok {
+      return "", NewTProtocolExceptionFromOsError(err)
+    }
+    return v, nil
+  }
+  s, err := p.ParseQuotedStringBody()
+  if err != nil {
+    return "", NewTProtocolExceptionFromOsError(err)
+  }
+  str := string(JSON_QUOTE) + line + s
+  v, ok := JsonUnquote(str)
+  if !ok {
+    return "", NewTProtocolException(INVALID_DATA, "Unable to parse as JSON string "+str)
+  }
+  return v, nil
+}
+
+func (p *TSimpleJSONProtocol) ParseQuotedStringBody() (string, TProtocolException) {
+  line, err := p.reader.ReadString(JSON_QUOTE)
+  if err != nil {
+    return "", NewTProtocolExceptionFromOsError(err)
+  }
+  l := len(line)
+  // count number of escapes to see if we need to keep going
+  i := 1
+  for ; i < l; i++ {
+    if line[l-i-1] != '\\' {
+      break
+    }
+  }
+  if i&0x01 == 1 {
+    return line, nil
+  }
+  s, err := p.ParseQuotedStringBody()
+  if err != nil {
+    return "", NewTProtocolExceptionFromOsError(err)
+  }
+  v := line + s
+  return v, nil
+}
+
+func (p *TSimpleJSONProtocol) ParseBase64EncodedBody() ([]byte, TProtocolException) {
+  line, err := p.reader.ReadBytes(JSON_QUOTE)
+  if err != nil {
+    return line, NewTProtocolExceptionFromOsError(err)
+  }
+  line2 := line[0 : len(line)-1]
+  l := len(line2)
+  output := make([]byte, base64.StdEncoding.DecodedLen(l))
+  n, err := base64.StdEncoding.Decode(output, line2)
+  return output[0:n], NewTProtocolExceptionFromOsError(err)
+}
+
+func (p *TSimpleJSONProtocol) ParseI64() (int64, bool, TProtocolException) {
+  if err := p.ParsePreValue(); err != nil {
+    return 0, false, err
+  }
+  var value int64
+  var isnull bool
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) {
+    p.reader.Read(b[0:len(JSON_NULL)])
+    isnull = true
+  } else {
+    num, err := p.readNumeric()
+    isnull = (num == nil)
+    if !isnull {
+      value = num.Int64()
+    }
+    if err != nil {
+      return value, isnull, err
+    }
+  }
+  return value, isnull, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ParseF64() (float64, bool, TProtocolException) {
+  if err := p.ParsePreValue(); err != nil {
+    return 0, false, err
+  }
+  var value float64
+  var isnull bool
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) {
+    p.reader.Read(b[0:len(JSON_NULL)])
+    isnull = true
+  } else {
+    num, err := p.readNumeric()
+    isnull = (num == nil)
+    if !isnull {
+      value = num.Float64()
+    }
+    if err != nil {
+      return value, isnull, err
+    }
+  }
+  return value, isnull, p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ParseObjectStart() (bool, TProtocolException) {
+  if err := p.ParsePreValue(); err != nil {
+    return false, err
+  }
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if len(b) > 0 && b[0] == JSON_LBRACE[0] {
+    p.reader.ReadByte()
+    p.parseContextStack.Push(int(_CONTEXT_IN_OBJECT_FIRST))
+    return false, nil
+  } else if len(b) >= len(JSON_NULL) && string(b[0:len(JSON_NULL)]) == string(JSON_NULL) {
+    return true, nil
+  }
+  return false, NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected '{' or null, but found '", string(b), "'"))
+}
+
+func (p *TSimpleJSONProtocol) ParseObjectEnd() TProtocolException {
+  if isNull, err := p.readIfNull(); isNull || err != nil {
+    return err
+  }
+  cxt := _ParseContext(p.parseContextStack.Last())
+  if cxt != _CONTEXT_IN_OBJECT_FIRST && cxt != _CONTEXT_IN_OBJECT_NEXT_KEY {
+    return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expected to be in the Object Context, but not in Object Context"))
+  }
+  line, err := p.reader.ReadString(JSON_RBRACE[0])
+  if err != nil {
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  for _, char := range line {
+    switch char {
+    default:
+      return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expecting end of object \"}\", but found: \"", line, "\""))
+    case ' ', '\n', '\r', '\t', '}':
+      break
+    }
+  }
+  p.parseContextStack.Pop()
+  return p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) ParseListBegin() (bool, TProtocolException) {
+  if e := p.ParsePreValue(); e != nil {
+    return false, e
+  }
+  b, e := p.reader.Peek(len(JSON_NULL))
+  if e == nil && len(b) >= 1 && b[0] == JSON_LBRACKET[0] {
+    p.parseContextStack.Push(int(_CONTEXT_IN_LIST_FIRST))
+    p.reader.ReadByte()
+    return false, nil
+  } else if e == nil && len(b) >= len(JSON_NULL) && string(b) == string(JSON_NULL) {
+    return true, nil
+  }
+  return false, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Expected 'null' or '{', received '%q'", b))
+}
+
+func (p *TSimpleJSONProtocol) ParseElemListBegin() (elemType TType, size int, e TProtocolException) {
+  if isNull, e := p.ParseListBegin(); isNull || e != nil {
+    return VOID, 0, e
+  }
+  bElemType, err := p.ReadByte()
+  elemType = TType(bElemType)
+  if err != nil {
+    return elemType, size, err
+  }
+  nSize, err2 := p.ReadI64()
+  size = int(nSize)
+  return elemType, size, err2
+}
+
+func (p *TSimpleJSONProtocol) ParseListEnd() TProtocolException {
+  if isNull, err := p.readIfNull(); isNull || err != nil {
+    return err
+  }
+  if _ParseContext(p.parseContextStack.Last()) != _CONTEXT_IN_LIST {
+    return NewTProtocolException(INVALID_DATA, "Expected to be in the List Context, but not in List Context")
+  }
+  line, err := p.reader.ReadString(JSON_RBRACKET[0])
+  if err != nil {
+    return NewTProtocolExceptionFromOsError(err)
+  }
+  for _, char := range line {
+    switch char {
+    default:
+      return NewTProtocolException(INVALID_DATA, fmt.Sprint("Expecting end of list \"]\", but found: \"", line, "\""))
+    case ' ', '\n', '\r', '\t', int(JSON_RBRACKET[0]):
+      break
+    }
+  }
+  p.parseContextStack.Pop()
+  return p.ParsePostValue()
+}
+
+func (p *TSimpleJSONProtocol) readSingleValue() (interface{}, TType, TProtocolException) {
+  e := p.readNonSignificantWhitespace()
+  if e != nil {
+    return nil, VOID, NewTProtocolExceptionFromOsError(e)
+  }
+  b, e := p.reader.Peek(10)
+  if len(b) > 0 {
+    c := b[0]
+    switch c {
+    case JSON_NULL[0]:
+      buf := make([]byte, len(JSON_NULL))
+      _, e := p.reader.Read(buf)
+      if e != nil {
+        return nil, VOID, NewTProtocolExceptionFromOsError(e)
+      }
+      if string(JSON_NULL) != string(buf) {
+        e := NewTProtocolException(INVALID_DATA, "Expected '"+string(JSON_NULL)+"' but found '"+string(buf)+"' while parsing JSON.")
+        return nil, VOID, e
+      }
+      return nil, VOID, nil
+    case JSON_QUOTE:
+      p.reader.ReadByte()
+      v, e := p.ParseStringBody()
+      if e != nil {
+        return v, UTF8, NewTProtocolExceptionFromOsError(e)
+      }
+      if v == JSON_INFINITY {
+        return INFINITY, DOUBLE, nil
+      } else if v == JSON_NEGATIVE_INFINITY {
+        return NEGATIVE_INFINITY, DOUBLE, nil
+      } else if v == JSON_NAN {
+        return NAN, DOUBLE, nil
+      }
+      return v, UTF8, nil
+    case JSON_TRUE[0]:
+      buf := make([]byte, len(JSON_TRUE))
+      _, e := p.reader.Read(buf)
+      if e != nil {
+        return true, BOOL, NewTProtocolExceptionFromOsError(e)
+      }
+      if string(JSON_TRUE) != string(buf) {
+        e := NewTProtocolException(INVALID_DATA, "Expected '"+string(JSON_TRUE)+"' but found '"+string(buf)+"' while parsing JSON.")
+        return true, BOOL, NewTProtocolExceptionFromOsError(e)
+      }
+      return true, BOOL, nil
+    case JSON_FALSE[0]:
+      buf := make([]byte, len(JSON_FALSE))
+      _, e := p.reader.Read(buf)
+      if e != nil {
+        return false, BOOL, NewTProtocolExceptionFromOsError(e)
+      }
+      if string(JSON_FALSE) != string(buf) {
+        e := NewTProtocolException(INVALID_DATA, "Expected '"+string(JSON_FALSE)+"' but found '"+string(buf)+"' while parsing JSON.")
+        return false, BOOL, NewTProtocolExceptionFromOsError(e)
+      }
+      return false, BOOL, nil
+    case JSON_LBRACKET[0]:
+      _, e := p.reader.ReadByte()
+      return make([]interface{}, 0), LIST, NewTProtocolExceptionFromOsError(e)
+    case JSON_LBRACE[0]:
+      _, e := p.reader.ReadByte()
+      return make(map[string]interface{}), STRUCT, NewTProtocolExceptionFromOsError(e)
+    case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'e', 'E', '.', '+', '-', JSON_INFINITY[0], JSON_NAN[0]:
+      // assume numeric
+      v, e := p.readNumeric()
+      return v, DOUBLE, e
+    default:
+      return nil, VOID, NewTProtocolException(INVALID_DATA, "Expected element in list but found '"+string(c)+"' while parsing JSON.")
+    }
+  }
+  return nil, VOID, NewTProtocolException(INVALID_DATA, "Cannot read a single element while parsing JSON.")
+
+}
+
+
+func (p *TSimpleJSONProtocol) readIfNull() (bool, TProtocolException) {
+  cont := true
+  for p.reader.Buffered() > 0 && cont {
+    b, _ := p.reader.Peek(1)
+    if len(b) < 1 {
+      return false, nil
+    }
+    switch b[0] {
+    default:
+      return false, nil
+    case JSON_NULL[0]:
+      cont = false
+      break
+    case ' ', '\n', '\r', '\t':
+      p.reader.ReadByte()
+      break
+    }
+  }
+  if p.reader.Buffered() == 0 {
+    return false, nil
+  }
+  b, _ := p.reader.Peek(len(JSON_NULL))
+  if string(b) == string(JSON_NULL) {
+    p.reader.Read(b[0:len(JSON_NULL)])
+    return true, nil
+  }
+  return false, nil
+}
+
+func (p *TSimpleJSONProtocol) readQuoteIfNext() {
+  if p.reader.Buffered() < 1 {
+    return
+  }
+  b, _ := p.reader.Peek(1)
+  if len(b) > 0 && b[0] == JSON_QUOTE {
+    p.reader.ReadByte()
+  }
+}
+
+func (p *TSimpleJSONProtocol) readNumeric() (Numeric, TProtocolException) {
+  isNull, err := p.readIfNull()
+  if isNull || err != nil {
+    return NUMERIC_NULL, err
+  }
+  hasDecimalPoint := false
+  nextCanBeSign := true
+  hasE := false
+  MAX_LEN := 40
+  buf := bytes.NewBuffer(make([]byte, 0, MAX_LEN))
+  continueFor := true
+  inQuotes := false
+  for continueFor {
+    c, err := p.reader.ReadByte()
+    if err != nil {
+      if err == os.EOF {
+        break
+      }
+      return NUMERIC_NULL, NewTProtocolExceptionFromOsError(err)
+    }
+    switch c {
+    case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+      buf.WriteByte(c)
+      nextCanBeSign = false
+    case '.':
+      if hasDecimalPoint {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number with multiple decimal points '%s.'", buf.String()))
+      }
+      if hasE {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number with decimal points in the exponent '%s.'", buf.String()))
+      }
+      buf.WriteByte(c)
+      hasDecimalPoint, nextCanBeSign = true, false
+    case 'e', 'E':
+      if hasE {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number with multiple exponents '%s%c'", buf.String(), c))
+      }
+      buf.WriteByte(c)
+      hasE, nextCanBeSign = true, true
+    case '-', '+':
+      if !nextCanBeSign {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprint("Negative sign within number"))
+      }
+      buf.WriteByte(c)
+      nextCanBeSign = false
+    case ' ', 0, '\t', '\n', '\r', JSON_RBRACE[0], JSON_RBRACKET[0], JSON_COMMA[0], JSON_COLON[0]:
+      p.reader.UnreadByte()
+      continueFor = false
+    case JSON_NAN[0]:
+      if buf.Len() == 0 {
+        buffer := make([]byte, len(JSON_NAN))
+        buffer[0] = c
+        _, e := p.reader.Read(buffer[1:])
+        if e != nil {
+          return NUMERIC_NULL, NewTProtocolExceptionFromOsError(e)
+        }
+        if JSON_NAN != string(buffer) {
+          e := NewTProtocolException(INVALID_DATA, "Expected '"+JSON_NAN+"' but found '"+string(buffer)+"' while parsing JSON.")
+          return NUMERIC_NULL, e
+        }
+        if inQuotes {
+          p.readQuoteIfNext()
+        }
+        return NAN, nil
+      } else {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number starting with character '%c'", c))
+      }
+    case JSON_INFINITY[0]:
+      if buf.Len() == 0 || (buf.Len() == 1 && buf.Bytes()[0] == '+') {
+        buffer := make([]byte, len(JSON_INFINITY))
+        buffer[0] = c
+        _, e := p.reader.Read(buffer[1:])
+        if e != nil {
+          return NUMERIC_NULL, NewTProtocolExceptionFromOsError(e)
+        }
+        if JSON_INFINITY != string(buffer) {
+          e := NewTProtocolException(INVALID_DATA, "Expected '"+JSON_INFINITY+"' but found '"+string(buffer)+"' while parsing JSON.")
+          return NUMERIC_NULL, e
+        }
+        if inQuotes {
+          p.readQuoteIfNext()
+        }
+        return INFINITY, nil
+      } else if buf.Len() == 1 && buf.Bytes()[0] == JSON_NEGATIVE_INFINITY[0] {
+        buffer := make([]byte, len(JSON_NEGATIVE_INFINITY))
+        buffer[0] = JSON_NEGATIVE_INFINITY[0]
+        buffer[1] = c
+        _, e := p.reader.Read(buffer[2:])
+        if e != nil {
+          return NUMERIC_NULL, NewTProtocolExceptionFromOsError(e)
+        }
+        if JSON_NEGATIVE_INFINITY != string(buffer) {
+          e := NewTProtocolException(INVALID_DATA, "Expected '"+JSON_NEGATIVE_INFINITY+"' but found '"+string(buffer)+"' while parsing JSON.")
+          return NUMERIC_NULL, e
+        }
+        if inQuotes {
+          p.readQuoteIfNext()
+        }
+        return NEGATIVE_INFINITY, nil
+      } else {
+        return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number starting with character '%c' due to existing buffer %s", c, buf.String()))
+      }
+    case JSON_QUOTE:
+      if !inQuotes {
+        inQuotes = true
+      } else {
+        break
+      }
+    default:
+      return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprintf("Unable to parse number starting with character '%c'", c))
+    }
+  }
+  if buf.Len() == 0 {
+    return NUMERIC_NULL, NewTProtocolException(INVALID_DATA, fmt.Sprint("Unable to parse number from empty string ''"))
+  }
+  return NewNumericFromJSONString(buf.String(), false), nil
+}
diff --git a/lib/go/thrift/tsimple_json_protocol_test.go b/lib/go/thrift/tsimple_json_protocol_test.go
new file mode 100644
index 0000000..e57d55b
--- /dev/null
+++ b/lib/go/thrift/tsimple_json_protocol_test.go
@@ -0,0 +1,662 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "encoding/base64"
+  "fmt"
+  "json"
+  "math"
+  "strconv"
+  "strings"
+  "testing"
+)
+
+func TestWriteSimpleJSONProtocolBool(t *testing.T) {
+  thetype := "boolean"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  for _, value := range BOOL_VALUES {
+    if e := p.WriteBool(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := false
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadSimpleJSONProtocolBool(t *testing.T) {
+  thetype := "boolean"
+  for _, value := range BOOL_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(trans)
+    if value {
+      trans.Write(JSON_TRUE)
+    } else {
+      trans.Write(JSON_FALSE)
+    }
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadBool()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteSimpleJSONProtocolByte(t *testing.T) {
+  thetype := "byte"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  for _, value := range BYTE_VALUES {
+    if e := p.WriteByte(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := byte(0)
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadSimpleJSONProtocolByte(t *testing.T) {
+  thetype := "byte"
+  for _, value := range BYTE_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(trans)
+    trans.WriteString(strconv.Itoa(int(value)))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadByte()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteSimpleJSONProtocolI16(t *testing.T) {
+  thetype := "int16"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  for _, value := range INT16_VALUES {
+    if e := p.WriteI16(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := int16(0)
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadSimpleJSONProtocolI16(t *testing.T) {
+  thetype := "int16"
+  for _, value := range INT16_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(trans)
+    trans.WriteString(strconv.Itoa(int(value)))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadI16()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteSimpleJSONProtocolI32(t *testing.T) {
+  thetype := "int32"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  for _, value := range INT32_VALUES {
+    if e := p.WriteI32(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := int32(0)
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadSimpleJSONProtocolI32(t *testing.T) {
+  thetype := "int32"
+  for _, value := range INT32_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(trans)
+    trans.WriteString(strconv.Itoa(int(value)))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadI32()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteSimpleJSONProtocolI64(t *testing.T) {
+  thetype := "int64"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  for _, value := range INT64_VALUES {
+    if e := p.WriteI64(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s != fmt.Sprint(value) {
+      t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+    }
+    v := int64(0)
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadSimpleJSONProtocolI64(t *testing.T) {
+  thetype := "int64"
+  for _, value := range INT64_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(trans)
+    trans.WriteString(strconv.Itoa64(value))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadI64()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteSimpleJSONProtocolDouble(t *testing.T) {
+  thetype := "double"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  for _, value := range DOUBLE_VALUES {
+    if e := p.WriteDouble(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if math.IsInf(value, 1) {
+      if s != JsonQuote(JSON_INFINITY) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_INFINITY))
+      }
+    } else if math.IsInf(value, -1) {
+      if s != JsonQuote(JSON_NEGATIVE_INFINITY) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_NEGATIVE_INFINITY))
+      }
+    } else if math.IsNaN(value) {
+      if s != JsonQuote(JSON_NAN) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, JsonQuote(JSON_NAN))
+      }
+    } else {
+      if s != fmt.Sprint(value) {
+        t.Fatalf("Bad value for %s %v: %s", thetype, value, s)
+      }
+      v := float64(0)
+      if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+      }
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadSimpleJSONProtocolDouble(t *testing.T) {
+  thetype := "double"
+  for _, value := range DOUBLE_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(trans)
+    n := NewNumericFromDouble(value)
+    trans.WriteString(n.String())
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadDouble()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if math.IsInf(value, 1) {
+      if !math.IsInf(v, 1) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v)
+      }
+    } else if math.IsInf(value, -1) {
+      if !math.IsInf(v, -1) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v)
+      }
+    } else if math.IsNaN(value) {
+      if !math.IsNaN(v) {
+        t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v)
+      }
+    } else {
+      if v != value {
+        t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+      }
+      if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+      }
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteSimpleJSONProtocolString(t *testing.T) {
+  thetype := "string"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  for _, value := range STRING_VALUES {
+    if e := p.WriteString(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if e := p.Flush(); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+    }
+    s := trans.String()
+    if s[0] != '"' || s[len(s)-1] != '"' {
+      t.Fatalf("Bad value for %s '%v', wrote '%v', expected: %v", thetype, value, s, fmt.Sprint("\"", value, "\""))
+    }
+    v := new(string)
+    if err := json.Unmarshal([]byte(s), v); err != nil || *v != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v)
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestReadSimpleJSONProtocolString(t *testing.T) {
+  thetype := "string"
+  for _, value := range STRING_VALUES {
+    trans := NewTMemoryBuffer()
+    p := NewTSimpleJSONProtocol(trans)
+    trans.WriteString(JsonQuote(value))
+    trans.Flush()
+    s := trans.String()
+    v, e := p.ReadString()
+    if e != nil {
+      t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+    }
+    if v != value {
+      t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v)
+    }
+    v1 := new(string)
+    if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != value {
+      t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1)
+    }
+    trans.Reset()
+    trans.Close()
+  }
+}
+
+func TestWriteSimpleJSONProtocolBinary(t *testing.T) {
+  thetype := "binary"
+  value := protocol_bdata
+  b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata)))
+  base64.StdEncoding.Encode(b64value, value)
+  b64String := string(b64value)
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  if e := p.WriteBinary(value); e != nil {
+    t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+  }
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.String())
+  }
+  s := trans.String()
+  if s != fmt.Sprint("\"", b64String, "\"") {
+    t.Fatalf("Bad value for %s %v\n  wrote: %v\nexpected: %v", thetype, value, s, "\""+b64String+"\"")
+  }
+  v1 := new(string)
+  if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String {
+    t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1)
+  }
+  trans.Close()
+}
+
+func TestReadSimpleJSONProtocolBinary(t *testing.T) {
+  thetype := "binary"
+  value := protocol_bdata
+  b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata)))
+  base64.StdEncoding.Encode(b64value, value)
+  b64String := string(b64value)
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  trans.WriteString(JsonQuote(b64String))
+  trans.Flush()
+  s := trans.String()
+  v, e := p.ReadBinary()
+  if e != nil {
+    t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.String())
+  }
+  if len(v) != len(value) {
+    t.Fatalf("Bad value for %s value length %v, wrote: %v, received length: %v", thetype, len(value), s, len(v))
+  }
+  for i := 0; i < len(v); i++ {
+    if v[i] != value[i] {
+      t.Fatalf("Bad value for %s at index %d value %v, wrote: %v, received: %v", thetype, i, value[i], s, v[i])
+    }
+  }
+  v1 := new(string)
+  if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String {
+    t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1)
+  }
+  trans.Reset()
+  trans.Close()
+}
+
+func TestWriteSimpleJSONProtocolList(t *testing.T) {
+  thetype := "list"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  p.WriteListBegin(TType(DOUBLE), len(DOUBLE_VALUES))
+  for _, value := range DOUBLE_VALUES {
+    if e := p.WriteDouble(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+  }
+  p.WriteListEnd()
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String())
+  }
+  str := trans.String()
+  str1 := new([]interface{})
+  err := json.Unmarshal([]byte(str), str1)
+  if err != nil {
+    t.Fatalf("Unable to decode %s, wrote: %s", thetype, str)
+  }
+  l := *str1
+  if len(l) < 2 {
+    t.Fatalf("List must be at least of length two to include metadata")
+  }
+  if int(l[0].(float64)) != DOUBLE {
+    t.Fatal("Invalid type for list, expected: ", DOUBLE, ", but was: ", l[0])
+  }
+  if int(l[1].(float64)) != len(DOUBLE_VALUES) {
+    t.Fatal("Invalid length for list, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1])
+  }
+  for k, value := range DOUBLE_VALUES {
+    s := l[k+2]
+    if math.IsInf(value, 1) {
+      if s.(string) != JSON_INFINITY {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_INFINITY), str)
+      }
+    } else if math.IsInf(value, 0) {
+      if s.(string) != JSON_NEGATIVE_INFINITY {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY), str)
+      }
+    } else if math.IsNaN(value) {
+      if s.(string) != JSON_NAN {
+        t.Fatalf("Bad value for %s at index %v  %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NAN), str)
+      }
+    } else {
+      if s.(float64) != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s)
+      }
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestWriteSimpleJSONProtocolSet(t *testing.T) {
+  thetype := "set"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  p.WriteSetBegin(TType(DOUBLE), len(DOUBLE_VALUES))
+  for _, value := range DOUBLE_VALUES {
+    if e := p.WriteDouble(value); e != nil {
+      t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.String())
+    }
+  }
+  p.WriteSetEnd()
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String())
+  }
+  str := trans.String()
+  str1 := new([]interface{})
+  err := json.Unmarshal([]byte(str), str1)
+  if err != nil {
+    t.Fatalf("Unable to decode %s, wrote: %s", thetype, str)
+  }
+  l := *str1
+  if len(l) < 2 {
+    t.Fatalf("Set must be at least of length two to include metadata")
+  }
+  if int(l[0].(float64)) != DOUBLE {
+    t.Fatal("Invalid type for set, expected: ", DOUBLE, ", but was: ", l[0])
+  }
+  if int(l[1].(float64)) != len(DOUBLE_VALUES) {
+    t.Fatal("Invalid length for set, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1])
+  }
+  for k, value := range DOUBLE_VALUES {
+    s := l[k+2]
+    if math.IsInf(value, 1) {
+      if s.(string) != JSON_INFINITY {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_INFINITY), str)
+      }
+    } else if math.IsInf(value, 0) {
+      if s.(string) != JSON_NEGATIVE_INFINITY {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY), str)
+      }
+    } else if math.IsNaN(value) {
+      if s.(string) != JSON_NAN {
+        t.Fatalf("Bad value for %s at index %v  %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, JsonQuote(JSON_NAN), str)
+      }
+    } else {
+      if s.(float64) != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s)
+      }
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+func TestWriteSimpleJSONProtocolMap(t *testing.T) {
+  thetype := "map"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  p.WriteMapBegin(TType(I32), TType(DOUBLE), len(DOUBLE_VALUES))
+  for k, value := range DOUBLE_VALUES {
+    if e := p.WriteI32(int32(k)); e != nil {
+      t.Fatalf("Unable to write %s key int32 value %v due to error: %s", thetype, k, e.String())
+    }
+    if e := p.WriteDouble(value); e != nil {
+      t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.String())
+    }
+  }
+  p.WriteMapEnd()
+  if e := p.Flush(); e != nil {
+    t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.String())
+  }
+  str := trans.String()
+  if str[0] != '[' || str[len(str)-1] != ']' {
+    t.Fatalf("Bad value for %s, wrote: %q, in go: %q", thetype, str, DOUBLE_VALUES)
+  }
+  l := strings.Split(str[1:len(str)-1], ",", -1)
+  if len(l) < 3 {
+    t.Fatal("Expected list of at least length 3 for map for metadata, but was of length ", len(l))
+  }
+  expectedKeyType, _ := strconv.Atoi(l[0])
+  expectedValueType, _ := strconv.Atoi(l[1])
+  expectedSize, _ := strconv.Atoi(l[2])
+  if expectedKeyType != I32 {
+    t.Fatal("Expected map key type ", I32, ", but was ", l[0])
+  }
+  if expectedValueType != DOUBLE {
+    t.Fatal("Expected map value type ", DOUBLE, ", but was ", l[1])
+  }
+  if expectedSize != len(DOUBLE_VALUES) {
+    t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", l[2])
+  }
+  for k, value := range DOUBLE_VALUES {
+    strk := l[k*2+3]
+    strv := l[k*2+4]
+    ik, err := strconv.Atoi(strk)
+    if err != nil {
+      t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, strk, string(k), err.String())
+    }
+    if ik != k {
+      t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v", thetype, k, strk, k)
+    }
+    s := strv
+    if math.IsInf(value, 1) {
+      if s != JsonQuote(JSON_INFINITY) {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_INFINITY))
+      }
+    } else if math.IsInf(value, 0) {
+      if s != JsonQuote(JSON_NEGATIVE_INFINITY) {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_NEGATIVE_INFINITY))
+      }
+    } else if math.IsNaN(value) {
+      if s != JsonQuote(JSON_NAN) {
+        t.Fatalf("Bad value for %s at index %v  %v, wrote: %v, expected: %v", thetype, k, value, s, JsonQuote(JSON_NAN))
+      }
+    } else {
+      expected := strconv.Ftoa64(value, 'g', 10)
+      if s != expected {
+        t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected %v", thetype, k, value, s, expected)
+      }
+      v := float64(0)
+      if err := json.Unmarshal([]byte(s), &v); err != nil || v != value {
+        t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v)
+      }
+    }
+    trans.Reset()
+  }
+  trans.Close()
+}
+
+
+func TestReadWriteSimpleJSONStruct(t *testing.T) {
+  thetype := "struct"
+  trans := NewTMemoryBuffer()
+  p := NewTSimpleJSONProtocol(trans)
+  orig := NewWork()
+  orig.Num1 = 25
+  orig.Num2 = 102
+  orig.Op = ADD
+  orig.Comment = "Add: 25 + 102"
+  if e := orig.Write(p); e != nil {
+    t.Fatalf("Unable to write %s value %#v due to error: %s", thetype, orig, e.String())
+  }
+  t.Log("Memory buffer contents: ", trans.String())
+  read := NewWork()
+  e := read.Read(p)
+  t.Logf("Read %s value: %#v", thetype, read)
+  if e != nil {
+    t.Fatalf("Unable to read %s due to error: %s", thetype, e.String())
+  }
+  if !orig.Equals(read) {
+    t.Fatalf("Original Write != Read: %#v != %#v ", orig, read)
+  }
+}
+
+func TestReadWriteSimpleJSONProtocol(t *testing.T) {
+  ReadWriteProtocolTest(t, NewTSimpleJSONProtocolFactory())
+}
diff --git a/lib/go/thrift/tsimple_server.go b/lib/go/thrift/tsimple_server.go
new file mode 100644
index 0000000..6c7d656
--- /dev/null
+++ b/lib/go/thrift/tsimple_server.go
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "os"
+)
+
+
+/**
+ * Simple singlethreaded server for testing.
+ *
+ */
+type TSimpleServer struct {
+  stopped bool
+
+  processorFactory       TProcessorFactory
+  serverTransport        TServerTransport
+  inputTransportFactory  TTransportFactory
+  outputTransportFactory TTransportFactory
+  inputProtocolFactory   TProtocolFactory
+  outputProtocolFactory  TProtocolFactory
+}
+
+func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer {
+  return NewTSimpleServerFactory2(NewTProcessorFactory(processor), serverTransport)
+}
+
+func NewTSimpleServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer {
+  return NewTSimpleServerFactory4(NewTProcessorFactory(processor),
+    serverTransport,
+    transportFactory,
+    protocolFactory,
+  )
+}
+
+func NewTSimpleServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer {
+  return NewTSimpleServerFactory6(NewTProcessorFactory(processor),
+    serverTransport,
+    inputTransportFactory,
+    outputTransportFactory,
+    inputProtocolFactory,
+    outputProtocolFactory,
+  )
+}
+
+func NewTSimpleServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TSimpleServer {
+  return NewTSimpleServerFactory6(processorFactory,
+    serverTransport,
+    NewTTransportFactory(),
+    NewTTransportFactory(),
+    NewTBinaryProtocolFactoryDefault(),
+    NewTBinaryProtocolFactoryDefault(),
+  )
+}
+
+func NewTSimpleServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer {
+  return NewTSimpleServerFactory6(processorFactory,
+    serverTransport,
+    transportFactory,
+    transportFactory,
+    protocolFactory,
+    protocolFactory,
+  )
+}
+
+func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer {
+  return &TSimpleServer{processorFactory: processorFactory,
+    serverTransport:        serverTransport,
+    inputTransportFactory:  inputTransportFactory,
+    outputTransportFactory: outputTransportFactory,
+    inputProtocolFactory:   inputProtocolFactory,
+    outputProtocolFactory:  outputProtocolFactory,
+  }
+}
+
+func (p *TSimpleServer) ProcessorFactory() TProcessorFactory {
+  return p.processorFactory
+}
+
+func (p *TSimpleServer) ServerTransport() TServerTransport {
+  return p.serverTransport
+}
+
+func (p *TSimpleServer) InputTransportFactory() TTransportFactory {
+  return p.inputTransportFactory
+}
+
+func (p *TSimpleServer) OutputTransportFactory() TTransportFactory {
+  return p.outputTransportFactory
+}
+
+func (p *TSimpleServer) InputProtocolFactory() TProtocolFactory {
+  return p.inputProtocolFactory
+}
+
+func (p *TSimpleServer) OutputProtocolFactory() TProtocolFactory {
+  return p.outputProtocolFactory
+}
+
+func (p *TSimpleServer) Serve() os.Error {
+  p.stopped = false
+  err := p.serverTransport.Listen()
+  if err != nil {
+    return err
+  }
+  for !p.stopped {
+    client, err := p.serverTransport.Accept()
+    if err != nil {
+      return err
+    }
+    if client != nil {
+      p.processRequest(client)
+    }
+  }
+  return nil
+}
+
+func (p *TSimpleServer) Stop() os.Error {
+  p.stopped = true
+  p.serverTransport.Interrupt()
+  return nil
+}
+
+func (p *TSimpleServer) processRequest(client TTransport) {
+  processor := p.processorFactory.GetProcessor(client)
+  inputTransport := p.inputTransportFactory.GetTransport(client)
+  outputTransport := p.outputTransportFactory.GetTransport(client)
+  inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport)
+  outputProtocol := p.outputProtocolFactory.GetProtocol(outputTransport)
+  if inputTransport != nil {
+    defer inputTransport.Close()
+  }
+  if outputTransport != nil {
+    defer outputTransport.Close()
+  }
+  for {
+    ok, e := processor.Process(inputProtocol, outputProtocol)
+    if e != nil {
+      if !p.stopped {
+        // TODO(pomack) log error
+        break
+      }
+    }
+    if !ok {
+      break
+    }
+  }
+}
diff --git a/lib/go/thrift/tsocket.go b/lib/go/thrift/tsocket.go
new file mode 100644
index 0000000..758c132
--- /dev/null
+++ b/lib/go/thrift/tsocket.go
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "net"
+  "os"
+  "bytes"
+)
+
+/**
+ * Socket implementation of the TTransport interface. To be commented soon!
+ *
+ */
+type TSocket struct {
+  writeBuffer *bytes.Buffer
+  /**
+   * Wrapped Socket object
+   */
+  conn net.Conn
+  /**
+   * Remote Addr
+   */
+  addr net.Addr
+  /**
+   * Socket timeout in nanoseconds
+   */
+  nsecTimeout int64
+}
+
+/**
+ * Constructor that takes an already created socket.
+ *
+ * @param socket Already created socket object
+ * @throws TTransportException if there is an error setting up the streams
+ */
+func NewTSocketConn(connection net.Conn) (*TSocket, TTransportException) {
+  address := connection.RemoteAddr()
+  if address == nil {
+    address = connection.LocalAddr()
+  }
+  p := &TSocket{conn: connection, addr: address, nsecTimeout: 0, writeBuffer: bytes.NewBuffer(make([]byte, 0, 4096))}
+  return p, nil
+}
+
+/**
+ * Creates a new unconnected socket that will connect to the given host
+ * on the given port.
+ *
+ * @param host Remote host
+ * @param port Remote port
+ */
+func NewTSocketAddr(address net.Addr) *TSocket {
+  return NewTSocket(address, 0)
+}
+
+/**
+ * Creates a new unconnected socket that will connect to the given host
+ * on the given port.
+ *
+ * @param host    Remote host
+ * @param port    Remote port
+ * @param nsecTimeout Socket timeout
+ */
+func NewTSocket(address net.Addr, nsecTimeout int64) *TSocket {
+  sock := &TSocket{addr: address, nsecTimeout: nsecTimeout, writeBuffer: bytes.NewBuffer(make([]byte, 0, 4096))}
+  return sock
+}
+
+/**
+ * Sets the socket timeout
+ *
+ * @param timeout Nanoseconds timeout
+ */
+func (p *TSocket) SetTimeout(nsecTimeout int64) os.Error {
+  p.nsecTimeout = nsecTimeout
+  if p.IsOpen() {
+    if err := p.conn.SetTimeout(nsecTimeout); err != nil {
+      LOGGER.Print("Could not set socket timeout.", err)
+      return err
+    }
+  }
+  return nil
+}
+
+/**
+ * Returns a reference to the underlying socket.
+ */
+func (p *TSocket) Conn() net.Conn {
+  return p.conn
+}
+
+/**
+ * Checks whether the socket is connected.
+ */
+func (p *TSocket) IsOpen() bool {
+  if p.conn == nil {
+    return false
+  }
+  return true
+}
+
+/**
+ * Connects the socket, creating a new socket object if necessary.
+ */
+func (p *TSocket) Open() os.Error {
+  if p.IsOpen() {
+    return NewTTransportException(ALREADY_OPEN, "Socket already connected.")
+  }
+  if p.addr == nil {
+    return NewTTransportException(NOT_OPEN, "Cannot open nil address.")
+  }
+  if len(p.addr.Network()) == 0 {
+    return NewTTransportException(NOT_OPEN, "Cannot open bad network name.")
+  }
+  if len(p.addr.String()) == 0 {
+    return NewTTransportException(NOT_OPEN, "Cannot open bad address.")
+  }
+  var err os.Error
+  if p.conn, err = net.Dial(p.addr.Network(), "", p.addr.String()); err != nil {
+    LOGGER.Print("Could not open socket", err.String())
+    return NewTTransportException(NOT_OPEN, err.String())
+  }
+  if p.conn != nil {
+    p.conn.SetTimeout(p.nsecTimeout)
+  }
+  return nil
+}
+
+/**
+ * Closes the socket.
+ */
+func (p *TSocket) Close() os.Error {
+  // Close the socket
+  if p.conn != nil {
+    err := p.conn.Close()
+    if err != nil {
+      LOGGER.Print("Could not close socket. ", err.String())
+      return err
+    }
+    p.conn = nil
+  }
+  return nil
+}
+
+
+func (p *TSocket) Read(buf []byte) (int, os.Error) {
+  if !p.IsOpen() {
+    return 0, NewTTransportException(NOT_OPEN, "Connection not open")
+  }
+  n, err := p.conn.Read(buf)
+  return n, NewTTransportExceptionFromOsError(err)
+}
+
+
+func (p *TSocket) ReadAll(buf []byte) (int, os.Error) {
+  return ReadAllTransport(p, buf)
+}
+
+func (p *TSocket) Write(buf []byte) (int, os.Error) {
+  if !p.IsOpen() {
+    return 0, NewTTransportException(NOT_OPEN, "Connection not open")
+  }
+  p.writeBuffer.Write(buf)
+  return len(buf), nil
+}
+
+func (p *TSocket) Peek() bool {
+  return p.IsOpen()
+}
+
+func (p *TSocket) Flush() os.Error {
+  if !p.IsOpen() {
+    return NewTTransportException(NOT_OPEN, "Connection not open")
+  }
+  _, err := p.writeBuffer.WriteTo(p.conn)
+  return NewTTransportExceptionFromOsError(err)
+}
+
+func (p *TSocket) Interrupt() os.Error {
+  if !p.IsOpen() {
+    return nil
+  }
+  // TODO(pomack) fix Interrupt as this is probably wrong
+  return p.conn.Close()
+}
diff --git a/lib/go/thrift/tstruct.go b/lib/go/thrift/tstruct.go
new file mode 100644
index 0000000..5eaffae
--- /dev/null
+++ b/lib/go/thrift/tstruct.go
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+/**
+ * Helper class that encapsulates struct metadata.
+ *
+ */
+type TStruct interface {
+  TFieldContainer
+  TStructName() string
+  ThriftName() string
+  TStructFields() TFieldContainer
+  String() string
+  AttributeFromFieldId(fieldId int) interface{}
+  AttributeFromFieldName(fieldName string) interface{}
+}
+
+type tStruct struct {
+  TFieldContainer
+  name string
+}
+
+func NewTStructEmpty(name string) TStruct {
+  return &tStruct{
+    name:            name,
+    TFieldContainer: NewTFieldContainer(make([]TField, 0, 0)),
+  }
+}
+
+func NewTStruct(name string, fields []TField) TStruct {
+  return &tStruct{
+    name:            name,
+    TFieldContainer: NewTFieldContainer(fields),
+  }
+}
+
+func (p *tStruct) TStructName() string {
+  return p.name
+}
+
+func (p *tStruct) ThriftName() string {
+  return p.name
+}
+
+func (p *tStruct) TStructFields() TFieldContainer {
+  return p.TFieldContainer
+}
+
+func (p *tStruct) String() string {
+  return p.name
+}
+
+func (p *tStruct) Equals(other interface{}) bool {
+  cmp, ok := p.CompareTo(other)
+  return ok && cmp == 0
+}
+
+func (p *tStruct) CompareTo(other interface{}) (int, bool) {
+  return TType(STRUCT).Compare(p, other)
+}
+
+func (p *tStruct) AttributeFromFieldId(fieldId int) interface{} {
+  return nil
+}
+
+func (p *tStruct) AttributeFromFieldName(fieldName string) interface{} {
+  return p.AttributeFromFieldId(p.FieldIdFromFieldName(fieldName))
+}
+
+
+var ANONYMOUS_STRUCT TStruct
+
+func init() {
+  ANONYMOUS_STRUCT = NewTStructEmpty("")
+}
diff --git a/lib/go/thrift/ttransport.go b/lib/go/thrift/ttransport.go
new file mode 100644
index 0000000..45557f8
--- /dev/null
+++ b/lib/go/thrift/ttransport.go
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "os"
+  "log"
+)
+
+type Flusher interface {
+  Flush() (err os.Error)
+}
+
+/**
+ * Generic class that encapsulates the I/O layer. This is basically a thin
+ * wrapper around the combined functionality of Java input/output streams.
+ *
+ */
+type TTransport interface {
+  /**
+   * Queries whether the transport is open.
+   *
+   * @return True if the transport is open.
+   */
+  IsOpen() bool
+
+  /**
+   * Opens the transport for reading/writing.
+   *
+   * @returns TTransportException if the transport could not be opened
+   */
+  Open() (err os.Error)
+
+  /**
+   * Closes the transport.
+   */
+  Close() (err os.Error)
+
+  /**
+   * Reads up to len bytes into buffer buf, starting att offset off.
+   *
+   * @param buf Array to read into
+   * @param off Index to start reading at
+   * @param len Maximum number of bytes to read
+   * @return The number of bytes actually read
+   * @return TTransportException if there was an error reading data
+   */
+  Read(buf []byte) (n int, err os.Error)
+
+  /**
+   * Guarantees that all of len bytes are actually read off the transport.
+   *
+   * @param buf Array to read into
+   * @param off Index to start reading at
+   * @param len Maximum number of bytes to read
+   * @return The number of bytes actually read, which must be equal to len
+   * @return TTransportException if there was an error reading data
+   */
+  ReadAll(buf []byte) (n int, err os.Error)
+
+  /**
+   * Writes the buffer to the output
+   *
+   * @param buf The output data buffer
+   * @return Number of bytes written
+   * @return TTransportException if an error occurs writing data
+   */
+  Write(buf []byte) (n int, err os.Error)
+
+  /**
+   * Flush any pending data out of a transport buffer.
+   *
+   * @return TTransportException if there was an error writing out data.
+   */
+  Flush() (err os.Error)
+
+  /**
+   * Is there more data to be read?
+   *
+   * @return True if the remote side is still alive and feeding us
+   */
+  Peek() bool
+}
+/*
+type TTransportBase struct {
+}
+
+func (p* TTransportBase) IsOpen() bool {
+  return false;
+};
+
+func (p* TTransportBase) Peek() bool {
+  return p.IsOpen();
+}
+
+func (p* TTransportBase) Open() os.Error {
+  return NewTTransportException(UNKNOWN, "Subclasses must implement TTransportBase.Open()");
+}
+
+func (p* TTransportBase) Close() os.Error {
+  return NewTTransportException(UNKNOWN, "Subclasses must implement TTransportBase.Close()");
+}
+
+func (p* TTransportBase) Read(buf []byte) (int, os.Error) {
+  return 0, NewTTransportExceptionDefaultString("Subclasses must implement TTransportBase.Read()");
+}
+
+func (p* TTransportBase) ReadAll(buf []byte) (n int, err os.Error){
+  ret := 0;
+  size := len(buf);
+  for (n < size) {
+    ret, err = p.Read(buf[n:]);
+    if ret <= 0 {
+      if err != nil {
+        err = NewTTransportExceptionDefaultString("Cannot read. Remote side has closed. Tried to read " + string(size) + " bytes, but only got " + string(n) + " bytes.");
+      }
+      return ret, err;
+    }
+    n += ret;
+  }
+  return n, err;
+}
+
+func (p* TTransportBase) Write(buf []byte) (int, os.Error) {
+  return 0, NewTTransportExceptionDefaultString("Subclasses must implement TTransportBase.Write()");
+}
+
+func (p* TTransportBase) Flush() os.Error {
+  return nil;
+}
+*/
+/**
+ * Guarantees that all of len bytes are actually read off the transport.
+ *
+ * @param buf Array to read into
+ * @param off Index to start reading at
+ * @param len Maximum number of bytes to read
+ * @return The number of bytes actually read, which must be equal to len
+ * @return TTransportException if there was an error reading data
+ */
+func ReadAllTransport(p TTransport, buf []byte) (n int, err os.Error) {
+  ret := 0
+  size := len(buf)
+  for n < size {
+    ret, err = p.Read(buf[n:])
+    if ret <= 0 {
+      if err != nil {
+        err = NewTTransportExceptionDefaultString("Cannot read. Remote side has closed. Tried to read " + string(size) + " bytes, but only got " + string(n) + " bytes.")
+      }
+      return ret, err
+    }
+    n += ret
+  }
+  return n, err
+}
+
+
+var (
+  LOGGER *log.Logger
+)
+
+func init() {
+  LOGGER = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
+}
diff --git a/lib/go/thrift/ttransport_exception.go b/lib/go/thrift/ttransport_exception.go
new file mode 100644
index 0000000..b9fae17
--- /dev/null
+++ b/lib/go/thrift/ttransport_exception.go
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+import (
+  "os"
+)
+
+/**
+ * Transport exceptions.
+ *
+ */
+type TTransportException interface {
+  TException
+  TypeId() int
+}
+
+const (
+  UNKNOWN_TRANSPORT_EXCEPTION = 0
+  NOT_OPEN                    = 1
+  ALREADY_OPEN                = 2
+  TIMED_OUT                   = 3
+  END_OF_FILE                 = 4
+)
+
+type tTransportException struct {
+  typeId  int
+  message string
+}
+
+func (p *tTransportException) TypeId() int {
+  return p.typeId
+}
+
+func (p *tTransportException) String() string {
+  return p.message
+}
+
+func NewTTransportExceptionDefault() TTransportException {
+  return NewTTransportExceptionDefaultType(UNKNOWN_TRANSPORT_EXCEPTION)
+}
+
+func NewTTransportExceptionDefaultType(t int) TTransportException {
+  return NewTTransportException(t, "")
+}
+
+func NewTTransportExceptionDefaultString(m string) TTransportException {
+  return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, m)
+}
+
+func NewTTransportException(t int, m string) TTransportException {
+  return &tTransportException{typeId: t, message: m}
+}
+
+func NewTTransportExceptionFromOsError(e os.Error) TTransportException {
+  if e == nil {
+    return nil
+  }
+  t, ok := e.(TTransportException)
+  if ok {
+    return t
+  }
+  if e == os.EOF {
+    return NewTTransportException(END_OF_FILE, e.String())
+  }
+  return NewTTransportExceptionDefaultString(e.String())
+}
diff --git a/lib/go/thrift/ttransport_factory.go b/lib/go/thrift/ttransport_factory.go
new file mode 100644
index 0000000..4ab4dbe
--- /dev/null
+++ b/lib/go/thrift/ttransport_factory.go
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift
+
+/**
+ * Factory class used to create wrapped instance of Transports.
+ * This is used primarily in servers, which get Transports from
+ * a ServerTransport and then may want to mutate them (i.e. create
+ * a BufferedTransport from the underlying base transport)
+ *
+ */
+type TTransportFactory interface {
+  GetTransport(trans TTransport) TTransport
+}
+
+type tTransportFactory struct{}
+
+/**
+ * Return a wrapped instance of the base Transport.
+ *
+ * @param trans The base transport
+ * @return Wrapped Transport
+ */
+func (p *tTransportFactory) GetTransport(trans TTransport) TTransport {
+  return trans
+}
+
+func NewTTransportFactory() TTransportFactory {
+  return &tTransportFactory{}
+}
diff --git a/lib/go/thrift/ttransport_test.go b/lib/go/thrift/ttransport_test.go
new file mode 100644
index 0000000..b9630de
--- /dev/null
+++ b/lib/go/thrift/ttransport_test.go
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package thrift_test
+
+import (
+  . "thrift"
+  "testing"
+  "net"
+  "os"
+  "strconv"
+)
+
+const TRANSPORT_BINARY_DATA_SIZE = 4096
+
+var (
+  transport_bdata []byte // test data for writing; same as data
+)
+
+func init() {
+  transport_bdata = make([]byte, TRANSPORT_BINARY_DATA_SIZE)
+  for i := 0; i < TRANSPORT_BINARY_DATA_SIZE; i++ {
+    transport_bdata[i] = byte((i + 'a') % 255)
+  }
+}
+
+func TransportTest(t *testing.T, writeTrans TTransport, readTrans TTransport) {
+  buf := make([]byte, TRANSPORT_BINARY_DATA_SIZE)
+  if !writeTrans.IsOpen() {
+    err := writeTrans.Open()
+    if err != nil {
+      t.Fatalf("Transport %T cannot open write transport: %s", writeTrans, err)
+    }
+  }
+  if !readTrans.IsOpen() {
+    err := readTrans.Open()
+    if err != nil {
+      t.Fatalf("Transport %T cannot open read transport: %s", readTrans, err)
+    }
+  }
+  _, err := writeTrans.Write(transport_bdata)
+  if err != nil {
+    t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err)
+  }
+  err = writeTrans.Flush()
+  if err != nil {
+    t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err)
+  }
+  n, err := readTrans.ReadAll(buf)
+  if err != nil {
+    t.Errorf("Transport %T cannot read binary data of length %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, err)
+  }
+  if n != TRANSPORT_BINARY_DATA_SIZE {
+    t.Errorf("Transport %T read only %d instead of %d bytes of binary data", readTrans, n, TRANSPORT_BINARY_DATA_SIZE)
+  }
+  for k, v := range buf {
+    if v != transport_bdata[k] {
+      t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k)
+    }
+  }
+  _, err = writeTrans.Write(transport_bdata)
+  if err != nil {
+    t.Fatalf("Transport %T cannot write binary data 2 of length %d: %s", writeTrans, len(transport_bdata), err)
+  }
+  err = writeTrans.Flush()
+  if err != nil {
+    t.Fatalf("Transport %T cannot flush write binary data 2: %s", writeTrans, err)
+  }
+  b := readTrans.Peek()
+  if b != true {
+    t.Errorf("Transport %T returned %s for Peek()", readTrans, b)
+  }
+  buf = make([]byte, TRANSPORT_BINARY_DATA_SIZE)
+  read := 1
+  for n = 0; n < TRANSPORT_BINARY_DATA_SIZE && read != 0; {
+    read, err = readTrans.Read(buf[n:])
+    if err != nil {
+      t.Errorf("Transport %T cannot read binary data 2 of total length %d from offset %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, n, err)
+    }
+    n += read
+  }
+  if n != TRANSPORT_BINARY_DATA_SIZE {
+    t.Errorf("Transport %T read only %d instead of %d bytes of binary data 2", readTrans, n, TRANSPORT_BINARY_DATA_SIZE)
+  }
+  for k, v := range buf {
+    if v != transport_bdata[k] {
+      t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k)
+    }
+  }
+}
+
+func CloseTransports(t *testing.T, readTrans TTransport, writeTrans TTransport) {
+  err := readTrans.Close()
+  if err != nil {
+    t.Errorf("Transport %T cannot close read transport: %s", readTrans, err)
+  }
+  if writeTrans != readTrans {
+    err = writeTrans.Close()
+    if err != nil {
+      t.Errorf("Transport %T cannot close write transport: %s", writeTrans, err)
+    }
+  }
+}
+
+func FindAvailableTCPServerPort(startPort int) (net.Addr, os.Error) {
+  for i := startPort; i < 65535; i++ {
+    s := "127.0.0.1:" + strconv.Itoa(i)
+    l, err := net.Listen("tcp", s)
+    if err == nil {
+      l.Close()
+      return net.ResolveTCPAddr(s)
+    }
+  }
+  return nil, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Could not find available server port")
+}
diff --git a/lib/go/thrift/ttype.go b/lib/go/thrift/ttype.go
new file mode 100644
index 0000000..d024b39
--- /dev/null
+++ b/lib/go/thrift/ttype.go
@@ -0,0 +1,975 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package thrift
+
+import (
+  "container/list"
+  "container/vector"
+  "strconv"
+)
+
+/**
+ * Type constants in the Thrift protocol.
+ */
+type TType byte
+
+const (
+  STOP    = 0
+  VOID    = 1
+  BOOL    = 2
+  BYTE    = 3
+  I08     = 3
+  DOUBLE  = 4
+  I16     = 6
+  I32     = 8
+  I64     = 10
+  STRING  = 11
+  UTF7    = 11
+  STRUCT  = 12
+  MAP     = 13
+  SET     = 14
+  LIST    = 15
+  ENUM    = 16
+  UTF8    = 16
+  UTF16   = 17
+  GENERIC = 127
+)
+
+func (p TType) String() string {
+  switch p {
+  case STOP:
+    return "STOP"
+  case VOID:
+    return "VOID"
+  case BOOL:
+    return "BOOL"
+  case BYTE:
+    return "BYTE"
+  case DOUBLE:
+    return "DOUBLE"
+  case I16:
+    return "I16"
+  case I32:
+    return "I32"
+  case I64:
+    return "I64"
+  case STRING:
+    return "STRING"
+  case STRUCT:
+    return "STRUCT"
+  case MAP:
+    return "MAP"
+  case SET:
+    return "SET"
+  case LIST:
+    return "LIST"
+  case ENUM:
+    return "ENUM"
+  case UTF16:
+    return "UTF16"
+  case GENERIC:
+    return "GENERIC"
+  }
+  return "Unknown"
+}
+
+func (p TType) IsBaseType() bool {
+  switch p {
+  case BOOL, BYTE, DOUBLE, I16, I32, I64, STRING, UTF8, UTF16:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsEmptyType() bool {
+  switch p {
+  case STOP, VOID:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsEnum() bool {
+  switch p {
+  case ENUM:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsNumericType() bool {
+  switch p {
+  case ENUM, BOOL, BYTE, DOUBLE, I16, I32, I64:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsStringType() bool {
+  switch p {
+  case STRING, UTF8, UTF16:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsContainer() bool {
+  switch p {
+  case MAP, SET, LIST:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsStruct() bool {
+  switch p {
+  case STRUCT:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsMap() bool {
+  switch p {
+  case MAP:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsList() bool {
+  switch p {
+  case LIST:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsSet() bool {
+  switch p {
+  case SET:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) IsInt() bool {
+  switch p {
+  case BYTE, I16, I32, I64:
+    return true
+  default:
+    return false
+  }
+  return false
+}
+
+func (p TType) Coerce(other interface{}) TType {
+  if other == nil {
+    return TType(STOP)
+  }
+  switch b := other.(type) {
+  default:
+    return TType(STOP)
+  case nil:
+    return TType(STOP)
+  case TType:
+    return b
+  case byte:
+    return TType(b)
+  case int:
+    return TType(byte(b))
+  case int8:
+    return TType(byte(b))
+  case int32:
+    return TType(byte(b))
+  case int64:
+    return TType(byte(b))
+  case uint:
+    return TType(byte(b))
+  case uint32:
+    return TType(byte(b))
+  case uint64:
+    return TType(byte(b))
+  case float32:
+    return TType(byte(int(b)))
+  case float64:
+    return TType(byte(int(b)))
+  }
+  return TType(STOP)
+}
+
+func (p TType) LessType(other interface{}) bool {
+  return p < p.Coerce(other)
+}
+
+func (p TType) Less(i, j interface{}) bool {
+  cmp, ok := p.Compare(i, j)
+  return ok && cmp > 0
+}
+
+
+func (p TType) Compare(i, j interface{}) (int, bool) {
+  if i == j {
+    return 0, true
+  }
+  if i == nil {
+    if j == nil {
+      return 0, true
+    }
+    return -1, true
+  }
+  if j == nil {
+    return 1, true
+  }
+  ci, iok := p.CoerceData(i)
+  cj, jok := p.CoerceData(j)
+  if iok && !jok {
+    return 1, true
+  }
+  if !iok && jok {
+    return -1, true
+  }
+  // hopefully this doesn't happen as Compare() would continuously return 0, false
+  if !iok && !jok {
+    return 0, false
+  }
+  if ci == cj {
+    return 0, true
+  }
+  if ci == nil {
+    if cj == nil {
+      return 0, true
+    }
+    return -1, true
+  }
+  if cj == nil {
+    return 1, true
+  }
+  switch p {
+  case STOP, VOID:
+    // hopefully this doesn't happen as Compare() would continuously return 0, false
+    return 0, false
+  case BOOL:
+    vi := ci.(bool)
+    vj := cj.(bool)
+    if vi == vj {
+      return 0, true
+    }
+    if vi == false {
+      return -1, true
+    }
+    return 1, true
+  case BYTE:
+    vi := ci.(byte)
+    vj := cj.(byte)
+    if vi == vj {
+      return 0, true
+    }
+    if vi < vj {
+      return -1, true
+    }
+    return 1, true
+  case DOUBLE:
+    vi := ci.(float64)
+    vj := cj.(float64)
+    if vi == vj {
+      return 0, true
+    }
+    if vi < vj {
+      return -1, true
+    }
+    return 1, true
+  case I16:
+    vi := ci.(int16)
+    vj := cj.(int16)
+    if vi == vj {
+      return 0, true
+    }
+    if vi < vj {
+      return -1, true
+    }
+    return 1, true
+  case I32:
+    vi := ci.(int32)
+    vj := cj.(int32)
+    if vi == vj {
+      return 0, true
+    }
+    if vi < vj {
+      return -1, true
+    }
+    return 1, true
+  case I64:
+    vi := ci.(int64)
+    vj := cj.(int64)
+    if vi == vj {
+      return 0, true
+    }
+    if vi < vj {
+      return -1, true
+    }
+    return 1, true
+  case STRING, UTF8, UTF16:
+    vi := ci.(string)
+    vj := cj.(string)
+    if vi == vj {
+      return 0, true
+    }
+    if vi < vj {
+      return -1, true
+    }
+    return 1, true
+  case STRUCT:
+    si := ci.(TStruct)
+    sj := cj.(TStruct)
+    if cmp := CompareString(si.ThriftName(), sj.ThriftName()); cmp != 0 {
+      return cmp, true
+    }
+    if cmp, ok := si.TStructFields().CompareTo(sj.TStructFields()); !ok || cmp != 0 {
+      return cmp, ok
+    }
+    for field := range si.TStructFields().Iter() {
+      a := si.AttributeFromFieldId(field.Id())
+      b := sj.AttributeFromFieldId(field.Id())
+      if cmp, ok := field.TypeId().Compare(a, b); !ok || cmp != 0 {
+        return cmp, ok
+      }
+    }
+    return 0, true
+  case MAP:
+    mi := ci.(TMap)
+    mj := cj.(TMap)
+    ei := mi.KeyType()
+    if ej := mj.KeyType(); ei != ej {
+      return CompareInt(int(ei), int(ej)), true
+    }
+    if size := mi.Len(); size != mj.Len() {
+      return CompareInt(size, mj.Len()), true
+    }
+    if c, cok := ei.Compare(mi.Keys(), mj.Keys()); c != 0 || !cok {
+      return c, cok
+    }
+    return ei.Compare(mi.Values(), mj.Values())
+  case LIST:
+    li := ci.(TList)
+    lj := cj.(TList)
+    ei := li.ElemType()
+    ej := lj.ElemType()
+    if ei != ej {
+      return CompareInt(int(ei), int(ej)), true
+    }
+    size := li.Len()
+    if size != lj.Len() {
+      return CompareInt(size, lj.Len()), true
+    }
+    for k := 0; k < size; k++ {
+      vi := li.At(k)
+      vj := lj.At(k)
+      c, cok := ei.Compare(vi, vj)
+      if c != 0 || !cok {
+        return c, cok
+      }
+    }
+    return 0, true
+  case SET:
+    li := ci.(TSet)
+    lj := cj.(TSet)
+    ei := li.ElemType()
+    ej := lj.ElemType()
+    if ei != ej {
+      return CompareInt(int(ei), int(ej)), true
+    }
+    size := li.Len()
+    if size != lj.Len() {
+      return CompareInt(size, lj.Len()), true
+    }
+    return ei.Compare(li.Values(), lj.Values())
+  default:
+    panic("Invalid thrift type to coerce")
+  }
+  return 0, false
+}
+
+func (p TType) CompareValueArrays(li, lj []interface{}) (int, bool) {
+  size := len(li)
+  if cmp := CompareInt(size, len(lj)); cmp != 0 {
+    return cmp, true
+  }
+  for i := 0; i < size; i++ {
+    vi := li[i]
+    vj := lj[i]
+    c, cok := p.Compare(vi, vj)
+    if c != 0 || !cok {
+      return c, cok
+    }
+  }
+  return 0, true
+}
+
+func (p TType) Equals(other interface{}) bool {
+  return p == p.Coerce(other)
+}
+
+type Stringer interface {
+  String() string
+}
+
+type Enumer interface {
+  String() string
+  Value() int
+  IsEnum() bool
+}
+
+func TypeFromValue(data interface{}) TType {
+  switch i := data.(type) {
+  default:
+    return STOP
+  case nil:
+    return VOID
+  case bool:
+    return BOOL
+  case float32, float64:
+    return DOUBLE
+  case int, int32:
+    return I32
+  case byte:
+    return BYTE
+  case int8:
+    return I08
+  case int16:
+    return I16
+  case int64:
+    return I64
+  case string:
+    return STRING
+  case TStruct:
+    return STRUCT
+  case TMap:
+    return MAP
+  case TSet:
+    return SET
+  case []interface{}, *list.List, *vector.Vector, TList:
+    return LIST
+  }
+  return STOP
+}
+
+func (p TType) CoerceData(data interface{}) (interface{}, bool) {
+  if data == nil {
+    switch p {
+    case STOP:
+      return nil, true
+    case VOID:
+      return nil, true
+    case BOOL:
+      return false, true
+    case BYTE:
+      return byte(0), true
+    case DOUBLE:
+      return float64(0), true
+    case I16:
+      return int16(0), true
+    case I32:
+      return int32(0), true
+    case I64:
+      return int64(0), true
+    case STRING, UTF8, UTF16:
+      return "", true
+    case STRUCT:
+      return NewTStructEmpty(""), true
+    case MAP:
+      return NewTMapDefault(), true
+    case LIST:
+      return NewTListDefault(), true
+    case SET:
+      return NewTSetDefault(), true
+    default:
+      panic("Invalid thrift type to coerce")
+    }
+  }
+  switch p {
+  case STOP:
+    return nil, true
+  case VOID:
+    return nil, true
+  case BOOL:
+    switch b := data.(type) {
+    default:
+      return false, false
+    case bool:
+      return b, true
+    case Numeric:
+      return bool(b.Int() != 0), true
+    case int:
+      return b != 0, true
+    case byte:
+      return b != 0, true
+    case int8:
+      return b != 0, true
+    case int16:
+      return b != 0, true
+    case int32:
+      return b != 0, true
+    case int64:
+      return b != 0, true
+    case uint:
+      return b != 0, true
+    case uint16:
+      return b != 0, true
+    case uint32:
+      return b != 0, true
+    case uint64:
+      return b != 0, true
+    case float32:
+      return b != 0, true
+    case float64:
+      return b != 0, true
+    case Stringer:
+      v := b.String()
+      if v == "false" || v == "0" || len(v) == 0 {
+        return false, true
+      }
+      return true, true
+    case string:
+      if b == "false" || b == "0" || len(b) == 0 {
+        return false, true
+      }
+      return true, true
+    }
+  case BYTE:
+    if b, ok := data.(byte); ok {
+      return b, true
+    }
+    if b, ok := data.(Numeric); ok {
+      return b.Byte(), true
+    }
+    if b, ok := data.(bool); ok {
+      if b {
+        return byte(1), true
+      }
+      return byte(0), true
+    }
+    if b, ok := data.(int); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(int8); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(int16); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(int32); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(int64); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(uint); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(uint8); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(uint16); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(uint32); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(uint64); ok {
+      return byte(b), true
+    }
+    if b, ok := data.(float32); ok {
+      return byte(int(b)), true
+    }
+    if b, ok := data.(float64); ok {
+      return byte(int(b)), true
+    }
+    if b, ok := data.(Stringer); ok {
+      data = b.String()
+    }
+    if b, ok := data.(string); ok {
+      i1, err := strconv.Atoi(b)
+      if err != nil {
+        return byte(int(i1)), true
+      }
+    }
+    return byte(0), false
+  case DOUBLE:
+    if b, ok := data.(float32); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(float64); ok {
+      return b, true
+    }
+    if b, ok := data.(Numeric); ok {
+      return bool(b.Float64() != 0.0), true
+    }
+    if b, ok := data.(byte); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(bool); ok {
+      if b {
+        return float64(1.0), true
+      }
+      return float64(0.0), true
+    }
+    if b, ok := data.(int); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(int8); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(int16); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(int32); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(int64); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(uint); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(uint8); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(uint16); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(uint32); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(uint64); ok {
+      return float64(b), true
+    }
+    if b, ok := data.(Stringer); ok {
+      data = b.String()
+    }
+    if b, ok := data.(string); ok {
+      d1, err := strconv.Atof64(b)
+      if err != nil {
+        return d1, true
+      }
+    }
+    return float64(0), false
+  case I16:
+    if b, ok := data.(int16); ok {
+      return b, true
+    }
+    if b, ok := data.(int); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(Numeric); ok {
+      return bool(b.Int16() != 0), true
+    }
+    if b, ok := data.(byte); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(bool); ok {
+      if b {
+        return int16(1.0), true
+      }
+      return int16(0.0), true
+    }
+    if b, ok := data.(int8); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(int32); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(int64); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(uint); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(uint8); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(uint16); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(uint32); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(uint64); ok {
+      return int16(b), true
+    }
+    if b, ok := data.(float32); ok {
+      return int16(int(b)), true
+    }
+    if b, ok := data.(float64); ok {
+      return int16(int(b)), true
+    }
+    if b, ok := data.(Stringer); ok {
+      data = b.String()
+    }
+    if b, ok := data.(string); ok {
+      i1, err := strconv.Atoi(b)
+      if err != nil {
+        return int16(i1), true
+      }
+    }
+    return int16(0), false
+  case I32:
+    if b, ok := data.(int32); ok {
+      return b, true
+    }
+    if b, ok := data.(int); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(Numeric); ok {
+      return bool(b.Int32() != 0), true
+    }
+    if b, ok := data.(byte); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(bool); ok {
+      if b {
+        return int32(1.0), true
+      }
+      return int32(0.0), true
+    }
+    if b, ok := data.(int8); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(int16); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(int64); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(uint); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(uint8); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(uint16); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(uint32); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(uint64); ok {
+      return int32(b), true
+    }
+    if b, ok := data.(float32); ok {
+      return int32(int(b)), true
+    }
+    if b, ok := data.(float64); ok {
+      return int32(int(b)), true
+    }
+    if b, ok := data.(Stringer); ok {
+      data = b.String()
+    }
+    if b, ok := data.(string); ok {
+      i1, err := strconv.Atoi(b)
+      if err != nil {
+        return int32(i1), true
+      }
+    }
+    return int32(0), false
+  case I64:
+    if b, ok := data.(int64); ok {
+      return b, true
+    }
+    if b, ok := data.(int32); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(int); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(Numeric); ok {
+      return bool(b.Int64() != 0), true
+    }
+    if b, ok := data.(byte); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(bool); ok {
+      if b {
+        return int64(1.0), true
+      }
+      return int64(0.0), true
+    }
+    if b, ok := data.(int8); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(int16); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(uint); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(uint8); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(uint16); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(uint32); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(uint64); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(float32); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(float64); ok {
+      return int64(b), true
+    }
+    if b, ok := data.(Stringer); ok {
+      data = b.String()
+    }
+    if b, ok := data.(string); ok {
+      i1, err := strconv.Atoi64(b)
+      if err != nil {
+        return i1, true
+      }
+    }
+    return int64(0), false
+  case STRING, UTF8, UTF16:
+    if b, ok := data.(Enumer); ok {
+      if i1, ok := data.(int); ok {
+        return i1, true
+      }
+      return b.String(), true
+    }
+    if b, ok := data.(Stringer); ok {
+      return b.String(), true
+    }
+    if b, ok := data.(string); ok {
+      return b, true
+    }
+    if b, ok := data.(int); ok {
+      return string(b), true
+    }
+    if b, ok := data.(byte); ok {
+      return string(b), true
+    }
+    if b, ok := data.(bool); ok {
+      if b {
+        return "true", true
+      }
+      return "false", true
+    }
+    if b, ok := data.(int8); ok {
+      return string(b), true
+    }
+    if b, ok := data.(int16); ok {
+      return string(b), true
+    }
+    if b, ok := data.(int32); ok {
+      return string(b), true
+    }
+    if b, ok := data.(int64); ok {
+      return string(b), true
+    }
+    if b, ok := data.(uint); ok {
+      return string(b), true
+    }
+    if b, ok := data.(uint8); ok {
+      return string(b), true
+    }
+    if b, ok := data.(uint16); ok {
+      return string(b), true
+    }
+    if b, ok := data.(uint32); ok {
+      return string(b), true
+    }
+    if b, ok := data.(uint64); ok {
+      return string(b), true
+    }
+    if b, ok := data.(float32); ok {
+      return strconv.Ftoa32(b, 'g', -1), true
+    }
+    if b, ok := data.(float64); ok {
+      return strconv.Ftoa64(b, 'g', -1), true
+    }
+    return "", false
+  case STRUCT:
+    if b, ok := data.(TStruct); ok {
+      return b, true
+    }
+    return NewTStructEmpty(""), true
+  case MAP:
+    if b, ok := data.(TMap); ok {
+      return b, true
+    }
+    return NewTMapDefault(), false
+  case LIST:
+    if b, ok := data.(TList); ok {
+      return b, true
+    }
+    return NewTListDefault(), false
+  case SET:
+    if b, ok := data.(TSet); ok {
+      return b, true
+    }
+    return NewTSetDefault(), false
+  default:
+    panic("Invalid thrift type to coerce")
+  }
+  return nil, false
+}
+
+type EqualsOtherInterface interface {
+  Equals(other interface{}) bool
+}
+
+type EqualsMap interface {
+  Equals(other TMap) bool
+}
+
+type EqualsSet interface {
+  Equals(other TSet) bool
+}
+
+type EqualsList interface {
+  Equals(other TList) bool
+}
+
+type EqualsStruct interface {
+  Equals(other TStruct) bool
+}