Interface in factory pattern and binary size increasing

135 views
Skip to first unread message

Xabi Martí

unread,
Nov 7, 2023, 8:42:42 AM11/7/23
to golang-nuts
Hi there, I've a problem with an increasing binary size and aws sdk.

I'm developing a cobra application for certain aws services with aws sdk v2, and I've a problem with a factory pattern, I've this code
```golang
package ec2

import (
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ec2"
)

type EC2Interface interface {
ListInstances() error
GetInstanceID(instanceTagName string) (string, error)
GetSecurityGroupsFrom(application string, environment string) ([]string, error)
GetSubnetsFromPrefix(prefix string) ([]string, error)
}

type EC2Client struct {
client *ec2.Client
}

func NewEC2Client(awscfg aws.Config) (*EC2Client, error) {
client := ec2.NewFromConfig(awscfg)
return &EC2Client{client: client}, nil
}
```

Here I'm returning the `*EC2Client` and I'm creating the client like this
```golang

ec2Client, err := ec2.NewEC2Client(awscfg)
if err != nil {
errors.CaptureException(err)
}
```
and calling it later functions like this
```golang
err = whatever.ExecuteOperation(*ecsClient, *ec2Client, *cwClient, project, env, command, "operations", maxRetries, secondsForRetry, synchronous, true, parsedEnvVars, servicesAsContainers)
```


so, I decided to use the Interface for the `NewEC2Client` and all the other clients (we use the same pattern with the other clients),
```golang
package ec2

import (
"context"

"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/ec2"
)

type EC2Client interface {
ListInstances() error
GetInstanceID(instanceTagName string) (string, error)
GetSecurityGroupsFrom(application string, environment string) ([]string, error)
GetSubnetsFromPrefix(prefix string) ([]string, error)
}

type awsEC2Client struct {
client *ec2.Client
}

func NewEC2Client(profile string) (EC2Client, error) {
awscfg, err := config.LoadDefaultConfig(
context.Background(),
config.WithSharedConfigProfile(profile),
)
if err != nil {
return nil, err
}
client := ec2.NewFromConfig(awscfg)
return &awsEC2Client{client: client}, nil
}
```
returning the Interface instead of the struct, for mocking, enforce the contract, decouple, etc.. and call the implementation like this
```golang

ec2Client, err := ec2.NewEC2Client(profile)
if err != nil {
errors.CaptureException(err)
}
...
err = whatever.ExecuteOperation(ecsClient, ec2Client, cwClient, project, env, command, "operations", maxRetries, secondsForRetry, synchronous, true, parsedEnvVars, servicesAsContainers)
```

to the function
```golang
func ExecuteOperation(ecsClient ecs.ECSClient, ec2Client ec2.EC2Client, cwClient cloudwatch.CWClient, project, environment, command, container string, maxRetries, secondsForRetry int, synchronous bool, notificationUser bool, envVars map[string]string, servicesAsContainers bool) error {
```


and it increase the size of the binary from 30Mb to 80Mb, I see the attached with the go-binsize-treemap tool

What is causing the increment of size? Any way to accomplish with the interfaces without growing the binary size? Or should I remove the interfaces as I'm not going to use any other implementation of the ec2 client?

Thanks a lot
image (5).png
image (4).png

Peter Galbavy

unread,
Nov 8, 2023, 3:33:58 AM11/8/23
to golang-nuts
Check the size of dependencies; From https://stackoverflow.com/questions/70764915/how-to-check-the-size-of-packages-linked-into-my-go-code the very last answer suggests:

go tool nm -size -sort size EXECUTABLE

Which has helped me locate unexpected lumps of imports. You can also build with  --ldflags '-s -w' to remove debug symbols. If size is a concern for distribution, look at "upx" to compress the binary.
Reply all
Reply to author
Forward
0 new messages