Skip to content

nguyengg/init-once

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Golang sync.Once improvements for intialisers

Go Reference

Get with:

go get github.com/nguyengg/init-once

init.Once makes sure the initialiser is called exactly once regardless of its return status:

package main

import (
	"context"

	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	ini "github.com/nguyengg/init-once"
)

type App struct {
	Client *s3.Client
	once   ini.Once
}

func (a *App) DoSomething(ctx context.Context) error {
	// because ini.Once is used, subsequent a.once.Do will always return the same error, nil or non-nil.
	if err := a.once.Do(func() error {
		return a.init(ctx)
	}); err != nil {
		return err
	}

	// there's no risk of a nil Client pointer here due to the err check above.
	// sync.Once with an extra initErr or sync.OnceValue would have been needed to achieve the same thing.
	_, _ = a.Client.GetObject(ctx, &s3.GetObjectInput{})

	return nil
}

func (a *App) init(ctx context.Context) error {
	if a.Client == nil {
		cfg, err := config.LoadDefaultConfig(ctx)
		if err != nil {
			return err
		}

		a.Client = s3.NewFromConfig(cfg)
	}

	return nil
}

If you want to be able to retry initilisation over and over until first success, use init.SuccessOnce:

package main

import (
	"context"

	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	ini "github.com/nguyengg/init-once"
)

type App struct {
	Client *s3.Client
	once   ini.SuccessOnce
}

func (a *App) DoSomething(ctx context.Context) error {
	// because ini.SuccessOnce is used, ini can be retried until its first success!
	if err := a.once.Do(func() error {
		return a.init(ctx)
	}); err != nil {
		return err
	}

	// there's still no risk of a nil Client pointer here due to the err check above.
	_, _ = a.Client.GetObject(ctx, &s3.GetObjectInput{})

	return nil
}

func (a *App) init(ctx context.Context) error {
	if a.Client == nil {
		cfg, err := config.LoadDefaultConfig(ctx)
		if err != nil {
			return err
		}

		a.Client = s3.NewFromConfig(cfg)
	}

	return nil
}

About

Golang sync.Once improvements for intialisers

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages