How Marshal Works And Alternatives

The Marshal function is the most convenient way to encode, but taking a look at how it works also provides alternatives, should you want them.

First, we'll look at the other BER encode functions that are generated. There are two general forms:

   func BerEncode<type name>(pctxt *asn1rt.OSRTContext, value <go type>) (err error)
   
   func (pvalue *<type name>) BerEncode(pctxt *asn1rt.OSRTContext) (err error)
        

Here are two examples from the employee sample:

   func BerEncodeEmployeeNumber(pctxt *asn1rt.OSRTContext, value int64) (err error)
   
   func (pvalue *Name) BerEncode(pctxt *asn1rt.OSRTContext) (err error)
        

The first form is used when the Go type for the ASN.1 type is a built-in Go type - so basically it is used for the simple, nonconstructed ASN.1 types. The second form is used when the Go type is a generated type.

Now we can look at the Marshal function to see what it does and how these functions are used:

   // Create context object to manage encoding
   pctxt := new(asn1rt.OSRTContext)
   pctxt.InitBerEncode(1024)   // Initialize for encoding
   ...     
   err = v.BerEncode(pctxt)   // Invoke the encode function; v is a generated type
   ...
   pctxt.FlushBuffer()
        
   return pctxt.GetBerEncData(), err   // access the encoded data