rticker

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 29, 2025 License: Unlicense Imports: 4 Imported by: 0

README

This package provides a ticker that can be reset, stopped, and closed.

I have come across situations where I would like to use a ticker, but I don't want to signal cancellation or closure with another channel or context. This package solves that problem, wrapping a time.Timer in a custom struct that acts as a ticker. When the custom ticker is stopped, any ticks are paused, but the read only channel remains open. When it is reset, ticks will begin again, or if reset while ticks are occuring, they will begin at the new duration added to the current time. If the ticker is closed, the associated receive channel is also closed, allowing any for range loops over the channel to terminate, helping to prevent leaking goroutines without an external mechanism to do so.

A simple example

package main

import (
	"fmt"
	"time"

	"github.com/tech10/rticker"
)

func main() {
	t := rticker.New(200 * time.Millisecond)

	count := 0
	for range t.C {
		count++
		fmt.Println("tick", count)
		if count == 3 {
			t.Close() // breaks the loop
		}
	}
	fmt.Println("Ticker closed.")
}

Docs

Read the complete documentation for this package for full examples and a complete overview on how each function works.

Documentation

Overview

Package rticker provides a resettable Ticker that can be reset to a new duration, and closed when not in use, which will subsequently close its receiving channel, helping to prevent goroutines from leaking.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrClosed = errors.New("ticker already closed")

Functions

This section is empty.

Types

type T

type T struct {
	C <-chan time.Time // read-only ticker channel
	// contains filtered or unexported fields
}

T is a ticker that wraps time.Timer and allows resetting the interval.

func New

func New(d time.Duration) *T

New creates a new T (ticker). d must not be less than or equal to 0, or a runtime panic is produced.

Example

ExampleNew demonstrates creating and using a basic resettable ticker.

package main

import (
	"fmt"
	"time"

	"github.com/tech10/rticker"
)

func main() {
	t := rticker.New(200 * time.Millisecond)

	count := 0
	for range t.C {
		count++
		fmt.Println("tick", count)
		if count == 3 {
			t.Close()
		}
	}
	fmt.Println("Ticker closed.")

}
Output:

tick 1
tick 2
tick 3
Ticker closed.

func NewWithContext

func NewWithContext(ctx context.Context, d time.Duration) *T

NewWithContext creates a resettable t (ticker) with a context. ctx must not be nil, or a runtime panic is produced. d must not be less than or equal to 0, or a runtime panic is produced.

Example

ExampleNewWithContext demonstrates creating a ticker that is canceled when its context is canceled.

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/tech10/rticker"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	t := rticker.NewWithContext(ctx, 30*time.Millisecond)
	defer t.Close()

	// read one tick
	<-t.C

	// cancel the context
	cancel()

	// wait until the ticker loop shuts down
	t.Wait()

	fmt.Println("context canceled, ticker closed:", t.IsClosed())

}
Output:

context canceled, ticker closed: true

func (*T) Close

func (rt *T) Close() error

Close stops the ticker permanently and closes the output channel. Returns ErrClosed if the ticker is already closed.

Example

ExampleT_Close demonstrates closing the ticker.

package main

import (
	"fmt"
	"time"

	"github.com/tech10/rticker"
)

func main() {
	t := rticker.New(20 * time.Millisecond)

	// consume one tick
	<-t.C

	t.Close()
	fmt.Println("closed:", t.IsClosed())

}
Output:

closed: true

func (*T) IsClosed

func (rt *T) IsClosed() bool

IsClosed checks if the ticker is closed.

func (*T) Reset

func (rt *T) Reset(d time.Duration) error

Reset resets the internal timer with the given interval. Returns ErrClosed if the ticker is closed.

Example

ExampleT_Reset demonstrates resetting a ticker to a different interval.

package main

import (
	"fmt"
	"time"

	"github.com/tech10/rticker"
)

func main() {
	t := rticker.New(100 * time.Millisecond)
	defer t.Close()

	<-t.C // first tick
	_ = t.Reset(50 * time.Millisecond)

	// We should now get a tick faster than before.
	<-t.C
	fmt.Println("reset worked")

}
Output:

reset worked

func (*T) Stop

func (rt *T) Stop() error

Stop stops the ticker temporarily. It can be reset again, and is merely paused. Returns ErrClosed if the ticker is closed.

Example

ExampleT_Stop demonstrates stopping and restarting the ticker.

package main

import (
	"fmt"
	"time"

	"github.com/tech10/rticker"
)

func main() {
	t := rticker.New(50 * time.Millisecond)
	defer t.Close()

	<-t.C
	_ = t.Stop()

	select {
	case <-t.C:
		fmt.Println("unexpected tick")
	case <-time.After(100 * time.Millisecond):
		fmt.Println("stopped successfully")
	}

	// Now restart
	_ = t.Reset(10 * time.Millisecond)
	<-t.C
	fmt.Println("restarted successfully")

}
Output:

stopped successfully
restarted successfully

func (*T) Wait

func (rt *T) Wait()

Wait waits until the ticker is closed.

Jump to

Keyboard shortcuts

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