Stable order maps for golang.
Find a file
2026-01-23 19:53:07 +03:00
.golangci.yml v1.0.0 2026-01-23 19:53:07 +03:00
go.mod v1.0.0 2026-01-23 19:53:07 +03:00
LICENSE v1.0.0 2026-01-23 19:53:07 +03:00
map.go v1.0.0 2026-01-23 19:53:07 +03:00
map_test.go v1.0.0 2026-01-23 19:53:07 +03:00
README.md v1.0.0 2026-01-23 19:53:07 +03:00

smap - Ordered and Concurrent-Safe Map for Go

License: GPL
v3

English version below

smap - это реализация упорядоченной и потокобезопасной карты (map) для языка программирования Go. Библиотека предоставляет структуру данных, которая сохраняет порядок вставки ключей и безопасна для одновременного доступа из нескольких горутин.

Особенности

  • Упорядоченность: Ключи сохраняют порядок вставки, в отличие от стандартной карты Go
  • Потокобезопасность: Все операции синхронизированы с использованием sync.RWMutex
  • Обобщения: Реализована с использованием обобщений Go 1.18+, что позволяет использовать любые сравнимые типы в качестве ключей
  • Итераторы: Предоставляет методы для итерации по ключам, значениям и парам ключ-значение

Установка

go get go.neonxp.ru/smap

Использование

package main

import (
    "fmt"
    "go.neonxp.ru/smap"
)

func main() {
	// New map with capacity = 10
	m := smap.Make[string, int](10)

	// Set example values
	m.Set("one", 1)
	m.Set("two", 2)
	m.Set("three", 3)

	// Get first value
	fmt.Println(`m.Get("one") =`, m.Get("one")) // m.Get("one") = 1

	// Get value with existence check
	if val, ok := m.Get2("one"); ok {
		fmt.Println(`m.Get2("one") =`, val)
	} else {
		fmt.Println(`m.Get2("one") = key not found`)
	}

	// Keys iteration
	for k := range m.Keys {
		fmt.Println("key iteration:", k)
	}
	// key iteration: one
	// key iteration: two
	// key iteration: three

	// Values iteration
	for v := range m.Values {
		fmt.Println("value iteration:", v)
	}
	// value iteration: 1
	// value iteration: 2
	// value iteration: 3

	// Key:Value pairs iteration
	for k, v := range m.Entries {
		fmt.Println("pairs iteration:", k, v)
	}
	// pairs iteration: one 1
	// pairs iteration: two 2
	// pairs iteration: three 3

	// Check if key exists
	fmt.Println("Has 'two':", m.Has("two")) // true

	// Delete a key
	m.Delete("two")

	// Check if key exists
	fmt.Println("Has 'two':", m.Has("two")) // false
}

API

Make[K comparable, V any](cap int) M[K, V]

Создает новую упорядоченную карту с заданной начальной ёмкостью.

func (m *M[K, V]) Get(k K) V

Возвращает значение по ключу. Если ключ не существует, возвращается нулевое значение типа V.

func (m *M[K, V]) Get2(k K) (v V, ok bool)

Возвращает значение по ключу и флаг наличия ключа. Возвращает (значение, true) если ключ существует, и (нулевое значение, false) если ключ отсутствует.

func (m *M[K, V]) Has(k K) bool

Проверяет наличие ключа в карте. Возвращает true, если ключ существует, и false, если ключ отсутствует.

func (m *M[K, V]) Set(k K, v V)

Устанавливает значение по ключу. Если ключ уже существует, значение обновляется. Ключ добавляется в список только при первой вставке, что сохраняет порядок вставки.

func (m *M[K, V]) Delete(k K)

Удаляет ключ и соответствующее значение из карты. Если ключ не существует, метод ничего не делает. После удаления ключа он больше не будет присутствовать в итерациях по карте.

func (m *M[K, V]) Keys(yield func(K) bool)

Итерируется по ключам в порядке вставки. Передает каждый ключ в функцию yield. Если функция yield возвращает false, итерация прекращается.

func (m *M[K, V]) Values(yield func(V) bool)

Итерируется по значениям в порядке вставки ключей. Передает каждое значение в функцию yield. Если функция yield возвращает false, итерация прекращается.

func (m *M[K, V]) Entries(yield func(K, V) bool)

Итерируется по парам ключ-значение в порядке вставки. Передает каждый ключ и значение в функцию yield. Если функция yield возвращает false, итерация прекращается.

Лицензия

Этот проект лицензирован в соответствии с GNU General Public License версии 3 (GPLv3). Подробности смотрите в файле LICENSE.

                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2026 Alexander NeonXP Kiryukhin <i@neonxp.ru>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

Ссылки

English Version

smap is an implementation of an ordered and concurrent-safe map for the Go programming language. The library provides a data structure that preserves insertion order of keys and is safe for concurrent access from multiple goroutines.

Features

  • Ordered: Keys maintain insertion order, unlike the standard Go map
  • Thread-safe: All operations are synchronized using sync.RWMutex
  • Generics: Implemented using Go 1.18+ generics, allowing any comparable types as keys
  • Iterators: Provides methods for iterating over keys, values, and key-value pairs

Installation

go get go.neonxp.ru/smap

Usage

package main

import (
    "fmt"
    "go.neonxp.ru/smap"
)

func main() {
	// New map with capacity = 10
	m := smap.Make[string, int](10)

	// Set example values
	m.Set("one", 1)
	m.Set("two", 2)
	m.Set("three", 3)

	// Get first value
	fmt.Println(`m.Get("one") =`, m.Get("one")) // m.Get("one") = 1

	// Get value with existence check
	if val, ok := m.Get2("one"); ok {
		fmt.Println(`m.Get2("one") =`, val)
	} else {
		fmt.Println(`m.Get2("one") = key not found`)
	}

	// Keys iteration
	for k := range m.Keys {
		fmt.Println("key iteration:", k)
	}
	// key iteration: one
	// key iteration: two
	// key iteration: three

	// Values iteration
	for v := range m.Values {
		fmt.Println("value iteration:", v)
	}
	// value iteration: 1
	// value iteration: 2
	// value iteration: 3

	// Key:Value pairs iteration
	for k, v := range m.Entries {
		fmt.Println("pairs iteration:", k, v)
	}
	// pairs iteration: one 1
	// pairs iteration: two 2
	// pairs iteration: three 3

	// Check if key exists
	fmt.Println("Has 'two':", m.Has("two")) // true

	// Delete a key
	m.Delete("two")

	// Check if key exists
	fmt.Println("Has 'two':", m.Has("two")) // false
}

API

Make[K comparable, V any](cap int) M[K, V]

Creates a new ordered map with the specified initial capacity.

func (m *M[K, V]) Get(k K) V

Returns the value for the given key. If the key does not exist, returns the zero value of type V.

func (m *M[K, V]) Get2(k K) (v V, ok bool)

Returns the value for the given key and a presence flag. Returns (value, true) if the key exists, and (zero value, false) if the key is absent.

func (m *M[K, V]) Has(k K) bool

Checks if a key is present in the map. Returns true if the key exists, and false if the key is absent.

func (m *M[K, V]) Set(k K, v V)

Sets the value for the given key. If the key already exists, the value is updated. The key is added to the list only on first insertion, preserving insertion order.

func (m *M[K, V]) Delete(k K)

Deletes the key and its corresponding value from the map. If the key does not exist, the method does nothing. After deletion, the key will no longer be present in map iterations.

func (m *M[K, V]) Keys(yield func(K) bool)

Iterates over keys in insertion order. Passes each key to the yield function. If the yield function returns false, iteration stops.

func (m *M[K, V]) Values(yield func(V) bool)

Iterates over values in key insertion order. Passes each value to the yield function. If the yield function returns false, iteration stops.

func (m *M[K, V]) Entries(yield func(K, V) bool)

Iterates over key-value pairs in insertion order. Passes each key and value to the yield function. If the yield function returns false, iteration stops.

License

This project is licensed under the GNU General Public License version 3 (GPLv3). See the LICENSE file for details.

                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2026 NeonXP
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.