Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// For format details, see https://aka.ms/devcontainer.json.
{
"name": "Ubuntu",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
"ghcr.io/devcontainers-extra/features/mise:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"postCreateCommand": "bash .devcontainer/post_create.sh",
"customizations": {
"vscode": {
"extensions": [
"golang.go"
]
}
}
}
13 changes: 13 additions & 0 deletions .devcontainer/post_create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

# note that bash will read from ~/.profile or ~/.bash_profile if the latter exists
# ergo, you may want to check to see which is defined on your system and only append to the existing file
echo 'eval "$(mise activate bash --shims)"' >>~/.bash_profile # this sets up non-interactive sessions
echo 'eval "$(mise activate bash)"' >>~/.bashrc # this sets up interactive sessions
Comment thread
min0625 marked this conversation as resolved.

mise trust .

mise install

mise exec -- go install -v golang.org/x/tools/gopls@latest
mise exec -- go install -v github.com/go-delve/delve/cmd/dlv@latest
51 changes: 51 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL"

on:
push:
branches:
- main
pull_request:
# The branches below must be a subset of the branches above
branches:
- main
schedule:
- cron: "0 17 * * 5"

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest

permissions:
# required for all workflows
security-events: write

strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
# TODO: Enable for javascript later
language: ["go"]

steps:
- name: Checkout repository
uses: actions/checkout@v5

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
25 changes: 25 additions & 0 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: PR Check

on:
pull_request:
branches:
- main

jobs:
check:
name: Lint & Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
Comment thread
min0625 marked this conversation as resolved.
with:
fetch-depth: 0

- name: Install mise
uses: jdx/mise-action@v4

- name: Download Go dependencies
run: go mod download

- name: Run check (lint + test)
run: make check
101 changes: 101 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# https://golangci-lint.run/docs/configuration/file/
version: "2"

run:
timeout: 5m

issues:
new: true
whole-files: true
new-from-rev: HEAD~
max-same-issues: 50

severity:
default: error
# rules:
# - linters:
# - dupl
# severity: error

formatters:
enable:
- gci
- gofmt
- gofumpt
- goimports
- golines
- swaggo
settings:
gofmt:
rewrite-rules:
- pattern: "interface{}"
replacement: "any"
gofumpt:
extra-rules: true
exclusions:
paths: []

linters:
default: none
enable:
# Standard
- errcheck
- govet
- ineffassign
- staticcheck
- unused

# Additional
- bodyclose
- depguard
- errname
- errorlint
- gocognit
- goconst
- goheader
- gomodguard
- goprintffuncname
- gosec
- nakedret
- nilerr
- nilnil
- noctx
- nolintlint
- prealloc
- promlinter
- revive
- testifylint
- testpackage
- thelper
- usestdlibvars
- wastedassign
- wsl_v5

disable: []

settings:
depguard:
rules:
main:
deny:
- pkg: github.com/pkg/errors
desc: Should be replaced by standard lib errors package
- pkg: golang.org/x/exp/slices
desc: Should be replaced by standard lib slices package
- pkg: github.com/go-resty/resty$
desc: Use github.com/go-resty/resty/v2 instead
- pkg: github.com/aws/smithy-go/ptr$
desc: Use github.com/aws/aws-sdk-go-v2/aws instead
govet:
enable:
- nilness

# exclusions:
# paths:
# - (.+)_test\.go
# rules:
# - path: (.+)_test\.go
# linters:
# - dupl
# - mnd
# - lll
2 changes: 0 additions & 2 deletions .tool-versions

This file was deleted.

17 changes: 17 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"go.useLanguageServer": true,
"go.toolsManagement.autoUpdate": true,
"go.lintTool": "golangci-lint-v2",
"go.lintFlags": [
"--path-mode=abs",
"--fast-only"
],
"go.alternateTools": {
"customFormatter": "golangci-lint-v2"
},
"go.formatTool": "custom",
"go.formatFlags": [
"fmt",
"--stdin"
]
}
46 changes: 46 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Agent Guidelines

This repository provides `gsyncmap` — a generic, type-safe wrapper around [`sync.Map`](https://pkg.go.dev/sync#Map) for Go.

## Repository Structure

| File | Description |
|------|-------------|
| `map.go` | `Map[Key, Value]` — generic concurrent map, value type can be `any` |
| `comparable_map.go` | `ComparableMap[Key, Value]` — variant requiring `comparable` value type |
| `map_test.go` | Unit tests |
| `map_example_test.go` | Runnable example tests (shown in pkg.go.dev) |

## Development Commands

```sh
# Run tests (with race detector)
make test
# go test -v -race -failfast ./...

# Run linter
make lint
# golangci-lint run -v ./...

# Run linter with auto-fix
make fix
# golangci-lint run -v --fix ./...

# Run lint + test together
make check
```

## Code Conventions

- **Go version**: 1.24+, module path `github.com/min0625/gsyncmap`
- All exported types and methods must have doc comments.
- `Map` wraps `sync.Map` via a direct type alias (`type Map[K, V] sync.Map`); avoid adding fields.
- `CompareAndDelete` / `CompareAndSwap` on `Map` are intentionally **deprecated** — do not un-deprecate them. Direct users to `ComparableMap` instead.
- Keep the two types (`Map` and `ComparableMap`) in sync: any new method added to one should be added to the other when applicable.
- New example functions must follow `Example*` naming conventions and include expected output comments so they serve as testable examples.

## Testing Guidelines

- All tests must pass with `-race` flag enabled.
- Cover both the normal (value found) and zero-value (key absent) code paths for every method.
- Do not add external test dependencies; use only the standard library.
25 changes: 6 additions & 19 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,23 +1,10 @@
MODULE_DIRS = . ./tools
fix:
golangci-lint run -v --fix ./...

gowork:
go work init . ./tools

tidy:
$(foreach dir,$(MODULE_DIRS), \
(cd $(dir) && go mod tidy) &&) true

install: tidy
cd tools && go install \
mvdan.cc/gofumpt

fmt: install
gofumpt -l -w -extra .

lint: install
golangci-lint run ./...
lint:
golangci-lint run -v ./...

test:
go test ./...
go test -v -race -failfast ./...

check: fmt lint test
check: lint test
50 changes: 45 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,38 @@
# Generic Sync Map
[![Go Reference](https://pkg.go.dev/badge/github.com/min0625/gsyncmap.svg)](https://pkg.go.dev/github.com/min0625/gsyncmap)


This Map is based on `generic` and `sync.Map`.
A generic, type-safe wrapper around [`sync.Map`](https://pkg.go.dev/sync#Map).

## Installation
```sh
go get github.com/min0625/gsyncmap
```

## Types

### `Map[Key comparable, Value any]`

A generic concurrent map that accepts any value type. Suitable for most use cases.

> **Note:** `CompareAndDelete` and `CompareAndSwap` are available on `Map` but deprecated.
> They may panic at runtime if `Value` is not a comparable type (e.g. slice, map, func).
> Use `ComparableMap` instead when these operations are needed.

### `ComparableMap[Key, Value comparable]`

A drop-in replacement for `Map` that requires the value type to be comparable.
Provides safe `CompareAndDelete` and `CompareAndSwap` without risk of runtime panic.

## Quick start

```go
package main

import "github.com/min0625/gsyncmap"
import (
"fmt"

"github.com/min0625/gsyncmap"
)

func main() {
var m gsyncmap.Map[string, string]
Expand All @@ -27,5 +46,26 @@ func main() {
}
```

## Example
See: [./map_example_test.go](./map_example_test.go)
When `CompareAndDelete` or `CompareAndSwap` is needed, use `ComparableMap`:

```go
package main

import (
"fmt"

"github.com/min0625/gsyncmap"
)

func main() {
var m gsyncmap.ComparableMap[string, string]

m.Store("k1", "v1")
fmt.Println(m.CompareAndSwap("k1", "v1", "v2")) // true
fmt.Println(m.Load("k1")) // v2 true
}
```

## Examples
See: [map_example_test.go](./map_example_test.go)

Loading
Loading