package
0.0.0-20250206045204-45fcc3025d35
Repository: https://github.com/romangurevitch/concurrencyworkshop.git
Documentation: pkg.go.dev

# README

Understanding Go's sync Package: Once

The sync package in Go provides synchronisation primitives to ensure safe concurrent access to shared resources.
One of these primitives is the Once type, which ensures that a piece of code is executed only once.

drawing

Table of Contents

  1. Introduction to Once
  2. Usage of Once
  3. Use Cases
  4. Common Pitfalls
  5. Best Practices
  6. Resources

Introduction to Once

The sync.Once type is a type of synchronisation primitive used to ensure that a particular piece of code is executed only once, regardless of how many goroutines attempt to execute it.
This is useful for initializing resources that are shared across multiple goroutines.

Usage of Once

Here's an example of how to use the sync.Once type:

package main

import (
	"fmt"
	"sync"
)

var once sync.Once

func main() {
	once.Do(initialize)
	once.Do(initialize) // initialize will not be called again
}

func initialize() {
	fmt.Println("Initializing...")
}

In this code:

  • A sync.Once variable named once is declared.
  • The Do method of once is called with a function initialize as an argument.
    The initialize function is executed the first time Do is called, but not the second time.

Examples and tests

See package

Use Cases

  • Lazy Initialisation:
    • sync.Once is useful for lazy initialisation where a resource is initialized only when it is needed.
  • Singleton Pattern:
    • Ensuring a single instance of a struct is created in a concurrent environment.
  • One-time Setup:
    • For setup that should only occur once but may be attempted from multiple goroutines.

Common Pitfalls

  • Dependency Cycles:
    • Be cautious of dependency cycles which could result in deadlocks when using sync.Once.
  • Error Handling:
    • sync.Once does not provide built-in error handling, so if the initialisation function can fail, you'll need to handle errors manually.

Best Practices

  • Error Handling:
    • Establish a robust error handling mechanism when using sync.Once for critical initialisation.
  • Idempotency:
    • Ensure the initialisation function is idempotent if it may be called multiple times outside of a sync.Once context.

Resources