gog

package module
v0.0.0-...-741771d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 8, 2024 License: Apache-2.0 Imports: 4 Imported by: 13

README

gog

Build Status Go Reference

General, generic extensions to the Go language, requiring generics (introduced in Go 1.18).

For now, the most simple, most obvious and most useful generics utilities.

Documentation

Overview

Package gog contains general, generic extensions to the Go language, requiring generics (introduced in Go 1.18).

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Coalesce

func Coalesce[T comparable](values ...T) (v T)

Coalesce returns the first non-zero value from listed arguments. Returns the zero value of the type parameter if no arguments are given or all are the zero value. Useful when you want to initialize a variable to the first non-zero value from a list of fallback values.

For example:

hostVal := Coalesce(hostName, os.Getenv("HOST"), "localhost")

Note: the same functionality has been added to Go 1.22 in cmp.Or()

func Deref

func Deref[T any](p *T, def ...T) (result T)

Deref "safely" dereferences a pointer, returns the pointed value. If the pointer is nil, the (first) def is returned. If def is not specified, the zero value of T is returned.

func First

func First[T any](first T, _ ...any) T

First returns the first argument. Useful when you want to use the first result of a function call that has more than one return values (e.g. in a composite literal or in a condition).

For example:

func f() (i, j, k int, s string, f float64) { return }

p := image.Point{
    X: First(f()),
}

func If

func If[T any](cond bool, vtrue, vfalse T) T

If returns vtrue if cond is true, vfalse otherwise.

Useful to avoid an if statement when initializing variables, for example:

min := If(i > 0, i, 0)

func Must

func Must[T any](v T, err error) T

Must takes 2 arguments, the second being an error. If err is not nil, Must panics. Else the first argument is returned.

Useful when inputs to some function are provided in the source code, and you are sure they are valid (if not, it's OK to panic). For example:

t := Must(time.Parse("2006-01-02", "2022-04-20"))

func Ptr

func Ptr[T any](v T) *T

Ptr returns a pointer to the passed value.

Useful when you have a value and need a pointer, e.g.:

func f() string { return "foo" }

foo := struct{
    Bar *string
}{
    Bar: Ptr(f()),
}

func RunEvictor

func RunEvictor(ctx context.Context, evictorPeriod time.Duration, opCaches ...interface{ Evict() })

RunEvictor should be run as a goroutine, it evicts expired cache entries from the listed OpCaches. Returns only if ctx is cancelled.

OpCache has Evict() method, so any OpCache can be listed (does not depend on the type parameter).

func Second

func Second[T any](_ any, second T, _ ...any) T

Second returns the second argument. Useful when you want to use the second result of a function call that has more than one return values (e.g. in a composite literal or in a condition).

For example:

func f() (i, j, k int, s string, f float64) { return }

p := image.Point{
    X: Second(f()),
}

func Third

func Third[T any](_, _ any, third T, _ ...any) T

Third returns the third argument. Useful when you want to use the third result of a function call that has more than one return values (e.g. in a composite literal or in a condition).

For example:

func f() (i, j, k int, s string, f float64) { return }

p := image.Point{
    X: Third(f()),
}

Types

type OpCache

type OpCache[T any] struct {
	// contains filtered or unexported fields
}

OpCache implements a general value cache. It can be used to cache results of arbitrary operations. Cached values are tied to a string key that should be derived from the operation's parameters. Cached values have an expiration time and also a grace period during which the cached value is considered valid, but getting a cached value during the grace period triggers a reload that will happen in the background (the cached value is returned immediately, without waiting).

Operations are captured by a function that returns a value of a certain type (T) and an error. If an operation has multiple results beside the error, they must be wrapped in a struct or slice.

Example

This example demonstrates how to use OpCache to cache the results of an existing function.

package main

import (
	"fmt"
	"time"

	"github.com/icza/gog"
)

func main() {
	type Point struct {
		X, Y    int
		Counter int
	}

	counter := 0
	// Existing GetPoint() function we want to add caching for:
	GetPoint := func(x, y int) (*Point, error) {
		counter++
		return &Point{X: x, Y: y, Counter: counter}, nil
	}

	var getPointCache = gog.NewOpCache[*Point](gog.OpCacheConfig{ResultExpiration: 100 * time.Millisecond})

	// Function to use which utilizes getPointCache (has identical signature to that of GetPoint):
	GetPointFast := func(x, y int) (*Point, error) {
		return getPointCache.Get(
			fmt.Sprint(x, y), // Key constructed from all params
			func() (*Point, error) { return GetPoint(x, y) },
		)
	}

	p, err := GetPointFast(1, 2) // This will call GetPoint()
	fmt.Printf("%+v %v\n", p, err)
	p, err = GetPointFast(1, 2) // This will come from the cache
	fmt.Printf("%+v %v\n", p, err)

	time.Sleep(110 * time.Millisecond)
	p, err = GetPointFast(1, 2) // Cache expired, will call GetPoint() again
	fmt.Printf("%+v %v\n", p, err)

}
Output:

&{X:1 Y:2 Counter:1} <nil>
&{X:1 Y:2 Counter:1} <nil>
&{X:1 Y:2 Counter:2} <nil>
Example (Multi_return)

This example demonstrates how to use OpCache to cache the results of an existing function that has multiple result types (besides the error).

package main

import (
	"fmt"
	"time"

	"github.com/icza/gog"
)

func main() {
	type Point struct {
		X, Y    int
		Counter int
	}

	counter := 0
	// Existing GetPoint() function we want to add caching for:
	GetPoint := func(x, y int) (*Point, int, error) {
		counter++
		return &Point{X: x, Y: 2 * x, Counter: counter}, counter * 10, fmt.Errorf("test_error_%d", counter)
	}

	// this type wraps the multiple return types of GetPoint():
	type multiResults struct {
		p *Point
		n int
	}
	var getPointCache = gog.NewOpCache[multiResults](gog.OpCacheConfig{ResultExpiration: 100 * time.Millisecond})

	// Function to use which utilizes getPointCache (has identical signature to that of GetPoint):
	GetPointFast := func(x, y int) (*Point, int, error) {
		mr, err := getPointCache.Get(
			fmt.Sprint(x, y), // Key constructed from all params
			func() (multiResults, error) {
				p, n, err := GetPoint(x, y)
				return multiResults{p, n}, err // packing multiple results
			},
		)
		return mr.p, mr.n, err // Unpacking multiple results
	}

	p, n, err := GetPointFast(1, 2) // This will call GetPoint()
	fmt.Printf("%+v %d %v\n", p, n, err)
	p, n, err = GetPointFast(1, 2) // This will come from the cache
	fmt.Printf("%+v %d %v\n", p, n, err)

	time.Sleep(110 * time.Millisecond)
	p, n, err = GetPointFast(1, 2) // Cache expired, will call GetPoint() again
	fmt.Printf("%+v %d %v\n", p, n, err)

}
Output:

&{X:1 Y:2 Counter:1} 10 test_error_1
&{X:1 Y:2 Counter:1} 10 test_error_1
&{X:1 Y:2 Counter:2} 20 test_error_2

func NewOpCache

func NewOpCache[T any](cfg OpCacheConfig) *OpCache[T]

NewOpCache creates a new OpCache.

func (*OpCache[T]) Evict

func (oc *OpCache[T]) Evict()

Evict checks all cached entries, and removes invalid ones.

func (*OpCache[T]) Get

func (oc *OpCache[T]) Get(
	key string,
	execOp func() (result T, err error),
) (result T, resultErr error)

Get gets the result of an operation.

If the result is cached and valid, it is returned immediately.

If the result is cached but not valid, but we're within the grace period, execOp() is called in the background to refresh the cache, and the cached result is returned immediately. Care is taken to only launch a single background worker to refresh the cache even if Get() is called multiple times with the same key before the cache can be refreshed.

Else result is either not cached or we're past the grace period: execOp() is executed, the function waits for its return values, the result is cached, and then the fresh result is returned.

type OpCacheConfig

type OpCacheConfig struct {
	// Operation results are valid for this long after creation.
	ResultExpiration time.Duration

	// Expired results are still usable for this long after expiration.
	// Tip: if this field is 0, grace period and thus background
	// op execution will be disabled.
	ResultGraceExpiration time.Duration
}

OpCacheConfig holds configuration options for OpCache.

Directories

Path Synopsis
Package slicesx provides generic slice utility functions.
Package slicesx provides generic slice utility functions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL