[fidl][golang] Exposing lazy marshaler

A lazy marshaler only creates the actual marshaler on first use, this
defering potentially costly operation. This is important as we move over
our bindings to this new pattern, to avoid all generated FIDL bindings
to do work on load.

Test: fx run-test go_fidl_test
Change-Id: I2a204114f788d477a24ef770547ef8be983edeca
diff --git a/src/syscall/zx/fidl/bindingstest/impl_new.go b/src/syscall/zx/fidl/bindingstest/impl_new.go
index 9715b66..645288b 100644
--- a/src/syscall/zx/fidl/bindingstest/impl_new.go
+++ b/src/syscall/zx/fidl/bindingstest/impl_new.go
@@ -10,151 +10,151 @@
 	_bindings "syscall/zx/fidl"
 )
 
-var _mTestSimple = _bindings.MustCreateMarshaler(TestSimple{})
+var _mTestSimple = _bindings.CreateLazyMarshaler(TestSimple{})
 
 func (msg *TestSimple) Marshaler() _bindings.Marshaler {
 	return _mTestSimple
 }
 
-var _mTestSimpleBool = _bindings.MustCreateMarshaler(TestSimpleBool{})
+var _mTestSimpleBool = _bindings.CreateLazyMarshaler(TestSimpleBool{})
 
 func (msg *TestSimpleBool) Marshaler() _bindings.Marshaler {
 	return _mTestSimpleBool
 }
 
-var _mTestAlignment1 = _bindings.MustCreateMarshaler(TestAlignment1{})
+var _mTestAlignment1 = _bindings.CreateLazyMarshaler(TestAlignment1{})
 
 func (msg *TestAlignment1) Marshaler() _bindings.Marshaler {
 	return _mTestAlignment1
 }
 
-var _mTestAlignment2 = _bindings.MustCreateMarshaler(TestAlignment2{})
+var _mTestAlignment2 = _bindings.CreateLazyMarshaler(TestAlignment2{})
 
 func (msg *TestAlignment2) Marshaler() _bindings.Marshaler {
 	return _mTestAlignment2
 }
 
-var _mTestFloat1 = _bindings.MustCreateMarshaler(TestFloat1{})
+var _mTestFloat1 = _bindings.CreateLazyMarshaler(TestFloat1{})
 
 func (msg *TestFloat1) Marshaler() _bindings.Marshaler {
 	return _mTestFloat1
 }
 
-var _mTestFloat2 = _bindings.MustCreateMarshaler(TestFloat2{})
+var _mTestFloat2 = _bindings.CreateLazyMarshaler(TestFloat2{})
 
 func (msg *TestFloat2) Marshaler() _bindings.Marshaler {
 	return _mTestFloat2
 }
 
-var _mTestFloat3 = _bindings.MustCreateMarshaler(TestFloat3{})
+var _mTestFloat3 = _bindings.CreateLazyMarshaler(TestFloat3{})
 
 func (msg *TestFloat3) Marshaler() _bindings.Marshaler {
 	return _mTestFloat3
 }
 
-var _mTestArray1 = _bindings.MustCreateMarshaler(TestArray1{})
+var _mTestArray1 = _bindings.CreateLazyMarshaler(TestArray1{})
 
 func (msg *TestArray1) Marshaler() _bindings.Marshaler {
 	return _mTestArray1
 }
 
-var _mTestArray2 = _bindings.MustCreateMarshaler(TestArray2{})
+var _mTestArray2 = _bindings.CreateLazyMarshaler(TestArray2{})
 
 func (msg *TestArray2) Marshaler() _bindings.Marshaler {
 	return _mTestArray2
 }
 
-var _mTestArray3 = _bindings.MustCreateMarshaler(TestArray3{})
+var _mTestArray3 = _bindings.CreateLazyMarshaler(TestArray3{})
 
 func (msg *TestArray3) Marshaler() _bindings.Marshaler {
 	return _mTestArray3
 }
 
-var _mTestArray4 = _bindings.MustCreateMarshaler(TestArray4{})
+var _mTestArray4 = _bindings.CreateLazyMarshaler(TestArray4{})
 
 func (msg *TestArray4) Marshaler() _bindings.Marshaler {
 	return _mTestArray4
 }
 
-var _mTestString1 = _bindings.MustCreateMarshaler(TestString1{})
+var _mTestString1 = _bindings.CreateLazyMarshaler(TestString1{})
 
 func (msg *TestString1) Marshaler() _bindings.Marshaler {
 	return _mTestString1
 }
 
-var _mTestString2 = _bindings.MustCreateMarshaler(TestString2{})
+var _mTestString2 = _bindings.CreateLazyMarshaler(TestString2{})
 
 func (msg *TestString2) Marshaler() _bindings.Marshaler {
 	return _mTestString2
 }
 
-var _mTestString3 = _bindings.MustCreateMarshaler(TestString3{})
+var _mTestString3 = _bindings.CreateLazyMarshaler(TestString3{})
 
 func (msg *TestString3) Marshaler() _bindings.Marshaler {
 	return _mTestString3
 }
 
-var _mTestVector1 = _bindings.MustCreateMarshaler(TestVector1{})
+var _mTestVector1 = _bindings.CreateLazyMarshaler(TestVector1{})
 
 func (msg *TestVector1) Marshaler() _bindings.Marshaler {
 	return _mTestVector1
 }
 
-var _mTestVector2 = _bindings.MustCreateMarshaler(TestVector2{})
+var _mTestVector2 = _bindings.CreateLazyMarshaler(TestVector2{})
 
 func (msg *TestVector2) Marshaler() _bindings.Marshaler {
 	return _mTestVector2
 }
 
-var _mTestStruct1 = _bindings.MustCreateMarshaler(TestStruct1{})
+var _mTestStruct1 = _bindings.CreateLazyMarshaler(TestStruct1{})
 
 func (msg *TestStruct1) Marshaler() _bindings.Marshaler {
 	return _mTestStruct1
 }
 
-var _mTestStruct2 = _bindings.MustCreateMarshaler(TestStruct2{})
+var _mTestStruct2 = _bindings.CreateLazyMarshaler(TestStruct2{})
 
 func (msg *TestStruct2) Marshaler() _bindings.Marshaler {
 	return _mTestStruct2
 }
 
-var _mTestUnion1 = _bindings.MustCreateMarshaler(TestUnion1{})
+var _mTestUnion1 = _bindings.CreateLazyMarshaler(TestUnion1{})
 
 func (msg *TestUnion1) Marshaler() _bindings.Marshaler {
 	return _mTestUnion1
 }
 
-var _mTestUnion2 = _bindings.MustCreateMarshaler(TestUnion2{})
+var _mTestUnion2 = _bindings.CreateLazyMarshaler(TestUnion2{})
 
 func (msg *TestUnion2) Marshaler() _bindings.Marshaler {
 	return _mTestUnion2
 }
 
-var _mTestHandle1 = _bindings.MustCreateMarshaler(TestHandle1{})
+var _mTestHandle1 = _bindings.CreateLazyMarshaler(TestHandle1{})
 
 func (msg *TestHandle1) Marshaler() _bindings.Marshaler {
 	return _mTestHandle1
 }
 
-var _mTestHandle2 = _bindings.MustCreateMarshaler(TestHandle2{})
+var _mTestHandle2 = _bindings.CreateLazyMarshaler(TestHandle2{})
 
 func (msg *TestHandle2) Marshaler() _bindings.Marshaler {
 	return _mTestHandle2
 }
 
-var _mTestInterface1 = _bindings.MustCreateMarshaler(TestInterface1{})
+var _mTestInterface1 = _bindings.CreateLazyMarshaler(TestInterface1{})
 
 func (msg *TestInterface1) Marshaler() _bindings.Marshaler {
 	return _mTestInterface1
 }
 
-var _mTestFuchsiaIoReadAtResponse = _bindings.MustCreateMarshaler(TestFuchsiaIoReadAtResponse{})
+var _mTestFuchsiaIoReadAtResponse = _bindings.CreateLazyMarshaler(TestFuchsiaIoReadAtResponse{})
 
 func (msg *TestFuchsiaIoReadAtResponse) Marshaler() _bindings.Marshaler {
 	return _mTestFuchsiaIoReadAtResponse
 }
 
-var _mTestFuchsiaIoWriteAtRequest = _bindings.MustCreateMarshaler(TestFuchsiaIoWriteAtRequest{})
+var _mTestFuchsiaIoWriteAtRequest = _bindings.CreateLazyMarshaler(TestFuchsiaIoWriteAtRequest{})
 
 func (msg *TestFuchsiaIoWriteAtRequest) Marshaler() _bindings.Marshaler {
 	return _mTestFuchsiaIoWriteAtRequest
diff --git a/src/syscall/zx/fidl/encoding_new.go b/src/syscall/zx/fidl/encoding_new.go
index be7758c..0d47a71 100644
--- a/src/syscall/zx/fidl/encoding_new.go
+++ b/src/syscall/zx/fidl/encoding_new.go
@@ -12,6 +12,7 @@
 	"reflect"
 	"strconv"
 	"strings"
+	"sync"
 	"syscall/zx"
 )
 
@@ -38,6 +39,61 @@
 	return nil, errors.New("unable to create marshaler for " + nicefmt(typ))
 }
 
+// CreateMarshaler creates a lazy marshaler from a sample struct. This lazy
+// marshaler initializes its actual delegate marshaler on first use, rather
+// than on creation. As a result, there is no validation on creation, and
+// instead the lazy marshaler will panic on first use if a marshaler
+// cannot be created of the sample provided.
+func CreateLazyMarshaler(sample interface{}) Marshaler {
+	return &lazyMarshaler{
+		sample: sample,
+	}
+}
+
+type lazyMarshaler struct {
+	sync.Mutex
+	sample   interface{}
+	delegate Marshaler
+}
+
+// Assert that lazyMarshaler implements the Marshaler interface.
+var _ Marshaler = &lazyMarshaler{}
+
+func (m *lazyMarshaler) init() {
+	m.Lock()
+	defer m.Unlock()
+
+	// Someone could have raced us between a call to init() and
+	// locking, avoid erroring out by referencing a nil sample.
+	if m.sample == nil {
+		return
+	}
+
+	m.delegate = MustCreateMarshaler(m.sample)
+	m.sample = nil
+}
+
+func (m *lazyMarshaler) getSize() int {
+	if m.delegate == nil {
+		m.init()
+	}
+	return m.delegate.getSize()
+}
+
+func (m *lazyMarshaler) marshal(v reflect.Value, out *encoder) error {
+	if m.delegate == nil {
+		m.init()
+	}
+	return m.delegate.marshal(v, out)
+}
+
+func (m *lazyMarshaler) unmarshal(in *decoder, v reflect.Value) error {
+	if m.delegate == nil {
+		m.init()
+	}
+	return m.delegate.unmarshal(in, v)
+}
+
 // MarshalNew marshals (or encodes) a message into the data and handles slices.
 func MarshalNew(message Message, data []byte, handles []zx.Handle) (int, int, error) {
 	// By construction, we know that message is a pointer to a struct since