@@ -309,12 +309,13 @@ func constructSliceCodec(t reflect.Type, seen seenMap) codec {
309309 e := t .Elem ()
310310 s := alignedSize (e )
311311
312+ var c codec
313+
312314 if e .Kind () == reflect .Uint8 {
313315 // Go 1.7+ behavior: slices of byte types (and aliases) may override the
314316 // default encoding and decoding behaviors by implementing marshaler and
315317 // unmarshaler interfaces.
316318 p := reflect .PointerTo (e )
317- c := codec {}
318319
319320 switch {
320321 case e .Implements (jsonMarshalerType ):
@@ -353,11 +354,26 @@ func constructSliceCodec(t reflect.Type, seen seenMap) codec {
353354 return c
354355 }
355356
356- c := constructCodec (e , seen , true )
357- return codec {
358- encode : constructSliceEncodeFunc (s , t , c .encode ),
359- decode : constructSliceDecodeFunc (s , t , c .decode ),
357+ inner := constructCodec (e , seen , true )
358+
359+ // If encode/decode functions are nil, that means this is a recursive type,
360+ // and so we can use delayed binding to define self-referential calls.
361+ if inner .encode == nil {
362+ inner .encode = func (e encoder , b []byte , p unsafe.Pointer ) ([]byte , error ) {
363+ return c .encode (e , b , p )
364+ }
360365 }
366+
367+ if inner .decode == nil {
368+ inner .decode = func (d decoder , b []byte , p unsafe.Pointer ) ([]byte , error ) {
369+ return c .decode (d , b , p )
370+ }
371+ }
372+
373+ c .encode = constructSliceEncodeFunc (s , t , inner .encode )
374+ c .decode = constructSliceDecodeFunc (s , t , inner .decode )
375+
376+ return c
361377}
362378
363379func constructSliceEncodeFunc (size uintptr , t reflect.Type , encode encodeFunc ) encodeFunc {
0 commit comments