Home > Back-end >  How to embed third party types in Go?
How to embed third party types in Go?

Time:01-10

In my application, the Decimal package github.com/shopspring/decimal is used.

In order to write custom functions on the decimal.Decimal type, I have created my own Decimal type and embedded decimal.Decimal:

type Decimal struct {
    decimal.Decimal
}

This works great, and I can now access decimal.Decimal methods on Decimal object:

a := Decimal{decimal.NewFromFloat(1.0)}
b := Decimal{a.Neg()}

Some of decimal.Decimal methods requires an argument of type decimal.Decimal, f.ex:

c := Decimal{a.Add(b)}

The above line cannot compile because of error: cannot use b (variable of type Decimal) as decimal.Decimal value in argument to a.Add

I have tried to convert Decimal to decimal.Decimal:

c := Decimal{a.Add((decimal.Decimal)(b))}

The above code would not compile due to below error:

cannot convert b (variable of type Decimal) to decimal.Decimal

Question: How to extend/embed a third party type in a way that allows the use of "parent" methods and can use the extended type as argument in methods that requires argument of parents type?

CodePudding user response:

A field declared with a type but no explicit field name is called an embedded field. An embedded field must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type. The unqualified type name acts as the field name.

So a quick and dirty solution would be to simply access the field using the "unqualified type name".

_ = Decimal{a.Add(b.Decimal)}

If, however, you're looking for a more seamless experience when using the new type, then your only option is to redeclare the methods that require the original type and use the new type in its place. These redeclared methods need only be simple wrappers that pass the embedded field of one instance to the method of the embedded field of the other instance. For example:

type Time struct {
    time.Time
}

func (t Time) In(loc *time.Location) Time {
    return Time{t.Time.In(loc)}
}

func (t Time) Equal(u Time) bool {
    return t.Time.Equal(u.Time)
}
  •  Tags:  
  • go
  • Related