mmkv

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 10, 2026 License: MIT Imports: 22 Imported by: 0

README

mmkv-go

A cgo-free implementation of Tencent MMKV for Go: a zero-copy read-only Reader plus a full read+write MMKV type. Both speak the official on-disk format and flock protocol, so they interoperate with the C++ library over the same files — without ever crossing the cgo boundary (reads are an order of magnitude faster than the official Go binding and allocate nothing on the view paths).

import "github.com/catundercar/mmkv-go"

// read-only, zero-copy (lock-free reads):
r, err := mmkv.Open("/path/to/mmkv/dir", "myID")
// encrypted: mmkv.Open(dir, id, mmkv.WithEncryption([]byte(cryptKey)))
if err != nil { /* ... */ }
defer r.Close()
v, ok := r.GetBytes("key")   // []byte view into the reader's buffer, zero-copy
n, ok := r.GetInt32("count")

// read+write (MMKV semantics: append fast path, single-key override,
// periodic compaction; multi-process via flock with WithMultiProcess()):
m, err := mmkv.MMKVWithID(dir, "myID")
if err != nil { /* ... */ }
defer m.Close()
_ = m.SetString("name", "value")
s, ok := m.GetString("name")

Freshness is transparent (like MMKV C++): each read cheaply checks the writer's change canary in the mmap'd .crc and reloads only when something changed. Cross-process single-writer + multi-reader is gated in CI with the writer on either side (cgo or pure Go).

Scope

  • Supported: read and write, plaintext or AES-CFB-128/256, key expiration, multi-process (flock interlock, WithMultiProcess), read-only mode, namespaces, backup/restore, ImportFrom, []string values, compareBeforeSet, content-changed handler, corruption recovery (WithRecoverOnError). POSIX (Linux/macOS) only.
  • Encryption: width follows key length, like MMKV (WithCryptKey / WithEncryption); the Reader also takes a custom Decryptor.
  • Key expiration: decoded and filtered transparently (expired keys read as absent).
  • Out of scope: Windows and Android-specific backends (ashmem); anything not listed above — the official cgo library remains the reference for those.

See doc/DESIGN.md for the on-disk format spec and boundaries, doc/MMKV_FULL_DESIGN.md for the read+write type's design, and doc/BENCHMARK.md for performance.

Why it's correct (and stays correct)

The headline guarantee is bidirectional equivalence with the official library: a value written by cgo reads back identically through this package (cgo.Get(k) == purego.Get(k)), and a file written by this package reads back identically through cgo — including encrypted and expiring stores. CI enforces both directions per MMKV version × architecture (harness/), so a format change in any MMKV release that breaks either side turns the build red.

Compatibility

CI verifies the equivalence guarantee against the latest tag of each MMKV release line, on both amd64 and arm64 (native runners):

MMKV line tested tag note
v1.2.x v1.2.16 earliest line tested
v1.3.x v1.3.16 format v4 / key expiration introduced
v2.0.x v2.0.2
v2.1.x v2.1.1 namespace
v2.2.x v2.2.4
v2.3.x v2.3.0 AES-256
v2.4.x v2.4.0 latest

On-disk format versions 0–4 are supported for reading. The format has been stable at v4 since v1.3.0, so files from current MMKV releases read correctly; a future format bump surfaces as ErrUnsupportedVersion (never silent corruption) and turns the CI differential red. The pure-Go writer emits format v4, so the write-direction differential is gated from v1.3 on (pre-v1.3 MMKV cannot read v4 files). Encryption (AES-CFB-128/256) and key expiration are differential-tested in both directions on v2.4.0; their on-disk format is version-stable.

Requires Go 1.23+ and a POSIX OS (Linux/macOS).

Layout

.                      pure-Go library (package mmkv) + unit tests + testdata/
doc/                   DESIGN.md, BENCHMARK.md
harness/               cgo module: cgo≡purego gate, -race concurrency, 3-way Go bench
cpp/                   native C++ baseline (bench_cpp.cpp, build.sh)
tools/gen/             cgo module: regenerate testdata fixtures
scripts/               build_output.sh, run_cell.sh, aggregate.py
.github/workflows/     CI matrix (versions × {amd64, arm64})

The root module is pure Go with no cgo dependency, so go get never pulls the C libraries, and go test ./... works out of the box (the cgo modules are excluded as separate modules). Everything that needs cgo (harness/, tools/gen/) is its own module with self-contained replace directives. For cross-module local dev, after building MMKV/output run go work init . ./harness ./tools/gen (go.work is gitignored).

Testing & benchmarks

CI runs a matrix over MMKV's major version lines × {amd64, arm64} on native runners. Each cell builds that MMKV version, runs the functional gate (hard fail), then the three-way performance comparison (C++ / cgo / purego).

# one cell locally (needs git, cmake, g++, zlib dev, Go):
bash scripts/build_output.sh v2.4.0          # clone+build MMKV into ./MMKV/output
bash scripts/run_cell.sh   v2.4.0 arm64      # gate + perf -> results/
python3 scripts/aggregate.py results         # merge -> markdown report

Pure-Go unit tests need no cgo: go test ./....

License

MIT. MMKV itself is BSD-3-Clause; this is a clean-room implementation of its on-disk format and locking protocol.

Documentation

Overview

Package mmkv is a cgo-free, read-only decoder for MMKV files. It parses the on-disk format directly in Go so the read path never crosses the cgo boundary. Writes are out of scope — keep using the official cgo library for those. See doc/DESIGN.md for the format spec and boundaries.

Scope: plaintext or AES-encrypted (WithEncryption), optional key expiration, read-only, single-writer/multi-reader.

Freshness, like MMKV C++: every read is transparently up to date. The reader mmaps ".crc" and, on each read, cheaply compares the writer's change canary (crcDigest, actualSize, sequence); when it changed it reloads the snapshot under a shared flock — interlocking with an MMKV writer opened MMKV_MULTI_PROCESS. No manual refresh, near-zero cost when nothing changed. POSIX-only (matches MMKV's flock + mmap).

Index

Constants

View Source
const ExpireNever uint32 = 0

ExpireNever, passed to EnableAutoKeyExpire, enables expiration without a common duration: keys never expire unless given a per-set duration (matches MMKV).

Variables

View Source
var (
	// ErrUnsupportedVersion guards against silent breakage on a future MMKV
	// on-disk format. Fall back to the cgo library when you see this.
	ErrUnsupportedVersion = errors.New("mmkv: unsupported MMKV file version")
	// ErrCRCMismatch means the data region failed its CRC32 check — corrupt,
	// torn write, or (commonly) an encrypted file read without (the right) key.
	ErrCRCMismatch = errors.New("mmkv: CRC mismatch")
)
View Source
var ErrClosed = errors.New("mmkv: instance closed")

ErrClosed is returned by operations on a closed MMKV.

View Source
var ErrReadOnly = errors.New("mmkv: instance is read-only")

ErrReadOnly is returned by mutating operations on a read-only instance.

Functions

func BackupOne

func BackupOne(rootDir, mmapID, dstDir string) error

BackupOne copies one MMKV instance (data file + ".crc") from rootDir to dstDir, producing a consistent, independently-readable snapshot. It holds a shared flock on ".crc" during the copy, so it is safe to run while an MMKV writer (opened MMKV_MULTI_PROCESS) is active — the writer's exclusive lock and this shared lock interlock. POSIX-only (matches MMKV's flock).

Backup is encryption-agnostic: it copies raw bytes, so encrypted instances back up fine without a key. Restore is a write operation and is intentionally out of scope — use the official cgo library's RestoreOneFromDirectory from the writer process.

func CheckExist

func CheckExist(rootDir, mmapID string) bool

CheckExist reports whether both the data file and its ".crc" exist.

func IsFileValid

func IsFileValid(rootDir, mmapID string) bool

IsFileValid reports whether the instance on disk is structurally valid: the meta parses to a supported version and the data region passes its CRC. Like MMKV's isFileValid, this is a structural check over the raw region (the CRC is over the ciphertext when encrypted), so it needs no key.

func RemoveStorage

func RemoveStorage(rootDir, mmapID string) error

RemoveStorage closes any cached instance for the file and unlinks both the data file and its ".crc" (matching MMKV's removeStorage: close, then delete).

func RestoreOneFromDirectory

func RestoreOneFromDirectory(rootDir, mmapID, srcDir string) error

RestoreOneFromDirectory restores one instance (data + ".crc") from srcDir into rootDir, overwriting in place. It holds an exclusive flock on the destination ".crc" for the whole copy (interlocking with multi-process instances and other processes) and writes with O_TRUNC, which preserves the inode so a live mmap stays valid — then it flags any cached instance to remap+reload on its next call. The pure-Go counterpart to BackupOne.

Coordination: a SINGLE-process instance takes no flock, so don't restore over one that is being concurrently accessed; restore over multi-process instances or while the file is idle (matches MMKV's restore contract).

Types

type Decryptor

type Decryptor interface {
	Decrypt(ciphertext, iv []byte) (plaintext []byte, err error)
}

Decryptor turns the on-disk (encrypted) data region into plaintext wire bytes. iv is the per-file IV from the meta file (.crc m_vector, 16 bytes) — it can change when the writer does a full write-back, so it is passed on every reload. Inject a custom one via WithDecryptor, or use WithEncryption for standard MMKV AES (AES-CFB-128; AES-128 or AES-256 chosen by key length).

type MMKV

type MMKV struct {
	// contains filtered or unexported fields
}

MMKV is a cgo-free, read+write MMKV instance: it reads and writes the official on-disk format and uses the same flock protocol, so it interoperates with the C++ library over the same files across processes. Open it with MMKVWithID.

Concurrency mirrors MMKV C++: every operation takes the instance thread lock (serializing goroutines) and, in multi-process mode, a cross-process flock on the ".crc" file (shared for reads, exclusive for writes); single-process mode skips the flock, keeping reads cheap. One instance is shared per file per process (see MMKVWithID).

View lifetime: GetBytes/GetString return zero-copy views into the live mapping that are valid only until the next call on this instance (a write or a cross-process reload can remap the data). Use the Copy variants to retain. POSIX-only (Linux + macOS).

func MMKVWithID

func MMKVWithID(rootDir, mmapID string, opts ...MMKVOption) (*MMKV, error)

MMKVWithID opens (or returns the already-open) read+write instance for <rootDir>/<encodeFilePath(mmapID)> (+ ".crc"). One instance is cached per file per process — concurrent callers get the same *MMKV, which is required for correctness (two instances would each flock the same fd without mutual exclusion and diverge in memory). POSIX-only.

func (*MMKV) ActualSize

func (m *MMKV) ActualSize() int

func (*MMKV) AllKeys

func (m *MMKV) AllKeys() []string

AllKeys returns all live (non-expired) keys, sorted.

func (*MMKV) Async

func (m *MMKV) Async() error

func (*MMKV) ClearAll

func (m *MMKV) ClearAll() error

ClearAll resets the instance to empty, truncating the data file back to the default size and bumping the sequence so other processes reload.

func (*MMKV) ClearMemoryCache

func (m *MMKV) ClearMemoryCache()

ClearMemoryCache drops the in-memory dictionary so the next access reloads from disk (matches MMKV's clearMemoryCache). It does not change the files.

func (*MMKV) Close

func (m *MMKV) Close() error

Close unmaps the files and drops the instance from the registry. Outstanding GetBytes/GetString views become invalid.

func (*MMKV) Contains

func (m *MMKV) Contains(key string) bool

Contains reports whether key is present.

func (*MMKV) Count

func (m *MMKV) Count() int

Count returns the number of keys.

func (*MMKV) DisableAutoKeyExpire

func (m *MMKV) DisableAutoKeyExpire() error

DisableAutoKeyExpire turns off expiration: it drops already-expired keys, strips the trailing timestamp from the rest, clears the meta flag, and rewrites.

func (*MMKV) DisableCompareBeforeSet

func (m *MMKV) DisableCompareBeforeSet()

DisableCompareBeforeSet turns off compare-before-set.

func (*MMKV) EnableAutoKeyExpire

func (m *MMKV) EnableAutoKeyExpire(seconds uint32) error

EnableAutoKeyExpire turns on key expiration with a default per-set duration in seconds (0 = ExpireNever, i.e. keys expire only with a per-set duration). It persists the flag in the meta and, on first enable, appends a never-expire timestamp to every existing value via a full write-back — so the on-disk format matches MMKV's enableAutoKeyExpire.

func (*MMKV) EnableCompareBeforeSet

func (m *MMKV) EnableCompareBeforeSet()

EnableCompareBeforeSet makes a Set a no-op when the stored value already equals the new one — avoiding write amplification for unchanged values. It is an in-memory, per-instance setting (not persisted) and is mutually exclusive with key expiration: it has no effect while expiration is enabled, and enabling expiration turns it off (matching MMKV).

func (*MMKV) Err

func (m *MMKV) Err() error

Err returns the last best-effort reload error, if any.

func (*MMKV) GetBool

func (m *MMKV) GetBool(key string) (bool, bool)

func (*MMKV) GetBytes

func (m *MMKV) GetBytes(key string) ([]byte, bool)

GetBytes returns a zero-copy view; valid only until the next call on this instance. Use GetBytesCopy to retain.

func (*MMKV) GetBytesCopy

func (m *MMKV) GetBytesCopy(key string) ([]byte, bool)

GetBytesCopy returns an independent copy of the value.

func (*MMKV) GetFloat32

func (m *MMKV) GetFloat32(key string) (float32, bool)

func (*MMKV) GetFloat64

func (m *MMKV) GetFloat64(key string) (float64, bool)

func (*MMKV) GetInt32

func (m *MMKV) GetInt32(key string) (int32, bool)

func (*MMKV) GetInt64

func (m *MMKV) GetInt64(key string) (int64, bool)

func (*MMKV) GetString

func (m *MMKV) GetString(key string) (string, bool)

GetString returns a zero-copy string view; valid only until the next call on this instance, and the bytes must not be mutated. Use GetStringCopy to retain.

func (*MMKV) GetStringCopy

func (m *MMKV) GetStringCopy(key string) (string, bool)

GetStringCopy returns the value as an independent string.

func (*MMKV) GetStringSlice

func (m *MMKV) GetStringSlice(key string) ([]string, bool)

GetStringSlice returns the value as a []string (MMKV's vector<string>). The strings are copies, so the result outlives the next call.

func (*MMKV) GetUInt32

func (m *MMKV) GetUInt32(key string) (uint32, bool)

func (*MMKV) GetUInt64

func (m *MMKV) GetUInt64(key string) (uint64, bool)

func (*MMKV) GetValueSize

func (m *MMKV) GetValueSize(key string) int

GetValueSize returns the number of stored value bytes for key (the encoded value, expire timestamp stripped), or -1 if absent.

func (*MMKV) ImportFrom

func (m *MMKV) ImportFrom(src *MMKV) (int, error)

ImportFrom copies every live key from src into this instance (applying this instance's expiration/compareBeforeSet policy), returning the number of keys imported. src is snapshotted under its own lock first, then written here, so two instances importing from each other can't deadlock.

func (*MMKV) IsCompareBeforeSetEnabled

func (m *MMKV) IsCompareBeforeSetEnabled() bool

IsCompareBeforeSetEnabled reports whether compare-before-set is on.

func (*MMKV) IsEncryptionEnabled

func (m *MMKV) IsEncryptionEnabled() bool

IsEncryptionEnabled reports whether the instance is AES-encrypted.

func (*MMKV) IsExpirationEnabled

func (m *MMKV) IsExpirationEnabled() bool

IsExpirationEnabled reports whether auto key expiration is on.

func (*MMKV) Lock

func (m *MMKV) Lock()

Lock / Unlock / TryLock expose MMKV's public cross-process exclusive lock for atomic read-modify-write across processes (matching MMKV::lock/unlock/try_lock).

Only the cross-process flock is held across the user's critical section; the thread mutex is taken just to manipulate the lock counters and released immediately, so ordinary Get/Set calls between Lock and Unlock do NOT deadlock (they re-enter the already-held exclusive flock by reference count). In single-process mode (no WithMultiProcess) these are no-ops, exactly like MMKV.

Usage:

m.Lock()
defer m.Unlock()
v, _ := m.GetInt32("counter")
m.SetInt32("counter", v+1)

func (*MMKV) MmapID

func (m *MMKV) MmapID() string

MmapID returns the instance's mmapID; RootDir returns its root directory.

func (*MMKV) ReKey

func (m *MMKV) ReKey(newKey []byte) error

ReKey changes the encryption key, re-encrypting the whole file via a full write-back (with a fresh IV). It also converts between plaintext and encrypted: pass a non-empty key to encrypt (or change the key), or an empty key to decrypt to plaintext. The new key takes effect only if the rewrite succeeds. AES width follows the key length (>16 bytes ⇒ AES-256).

func (*MMKV) RemoveValueForKey

func (m *MMKV) RemoveValueForKey(key string) error

RemoveValueForKey deletes key. It appends an empty-value tombstone when it fits (durable + visible cross-process), else compacts via a full write-back.

func (*MMKV) RemoveValuesForKeys

func (m *MMKV) RemoveValuesForKeys(keys []string) error

RemoveValuesForKeys deletes several keys, compacting once.

func (*MMKV) RootDir

func (m *MMKV) RootDir() string

func (*MMKV) SetBool

func (m *MMKV) SetBool(key string, v bool) error

func (*MMKV) SetBytes

func (m *MMKV) SetBytes(key string, v []byte) error

func (*MMKV) SetFloat32

func (m *MMKV) SetFloat32(key string, v float32) error

func (*MMKV) SetFloat64

func (m *MMKV) SetFloat64(key string, v float64) error

func (*MMKV) SetInt32

func (m *MMKV) SetInt32(key string, v int32) error

func (*MMKV) SetInt64

func (m *MMKV) SetInt64(key string, v int64) error

func (*MMKV) SetString

func (m *MMKV) SetString(key, v string) error

func (*MMKV) SetStringSlice

func (m *MMKV) SetStringSlice(key string, v []string) error

SetStringSlice stores a []string (MMKV's vector<string>).

func (*MMKV) SetUInt32

func (m *MMKV) SetUInt32(key string, v uint32) error

func (*MMKV) SetUInt64

func (m *MMKV) SetUInt64(key string, v uint64) error

func (*MMKV) Sync

func (m *MMKV) Sync() error

Sync flushes pending writes to disk durably (MS_SYNC); Async uses MS_ASYNC.

func (*MMKV) TotalSize

func (m *MMKV) TotalSize() int

TotalSize returns the data file size (bytes). ActualSize returns the bytes of the live KV region.

func (*MMKV) Trim

func (m *MMKV) Trim() error

Trim compacts the store (a full write-back) and then shrinks the data file toward ~2x the live size, floored at one page — matching MMKV's trim().

func (*MMKV) TryLock

func (m *MMKV) TryLock() bool

TryLock attempts the exclusive cross-process lock without blocking; it returns true if acquired (always true in single-process mode).

func (*MMKV) Unlock

func (m *MMKV) Unlock()

func (*MMKV) WriteValueToBuffer

func (m *MMKV) WriteValueToBuffer(key string, buf []byte) int

WriteValueToBuffer copies the stored value bytes for key into buf and returns the number copied, or -1 if the key is absent or buf is too small.

type MMKVOption

type MMKVOption func(*mmkvConfig)

MMKVOption configures an MMKV instance at open time.

func WithContentChangedHandler

func WithContentChangedHandler(fn func()) MMKVOption

WithContentChangedHandler registers a callback invoked after the instance reloads because another process changed the file (multi-process mode). It runs while the instance lock is held, so do not call back into this instance from it; keep it short.

func WithCryptKey

func WithCryptKey(key []byte) MMKVOption

WithCryptKey opens an AES-encrypted instance. The AES width follows MMKV: a key longer than 16 bytes selects AES-256, otherwise AES-128 (truncated/zero- padded). Pass the same key the file was written with; open the same file with consistent options across the process (the instance is cached by path).

func WithMultiProcess

func WithMultiProcess() MMKVOption

WithMultiProcess opens the instance for cross-process use: every read takes a shared flock and every write an exclusive flock on the ".crc" file, interlocking with other processes (Go or C++). The writer side of any process sharing the file MUST also be multi-process. Without it, flock is skipped and reads stay fast (single-process, like MMKV's default).

func WithReadOnly

func WithReadOnly() MMKVOption

WithReadOnly opens the instance read-only: the files are mapped O_RDONLY and every mutating call returns ErrReadOnly. The file must already exist. This is the single-type way to read a store you must not (or cannot) write.

func WithRecoverOnError

func WithRecoverOnError() MMKVOption

WithRecoverOnError salvages as much as possible (greedy decode) when the data region fails its CRC and the last-confirmed snapshot can't be restored either, instead of discarding to empty (MMKV's OnErrorRecover). A writable open then repairs the store immediately with a full write-back; a salvage during a cross-process reload is repaired by the next write. Read-only instances just serve the salvaged view.

type NameSpace

type NameSpace struct {
	// contains filtered or unexported fields
}

NameSpace reads MMKV instances stored under a custom root directory — MMKV's "namespace". A namespace is nothing more than a different rootDir; this type is sugar so callers don't repeat the path. Instances created by the cgo side via GetNameSpace(rootDir).MMKVWithID(id) live at <rootDir>/<encodeFilePath(id)>.

func OpenNameSpace

func OpenNameSpace(rootDir string) NameSpace

OpenNameSpace returns a NameSpace rooted at rootDir.

func (NameSpace) BackupOne

func (ns NameSpace) BackupOne(mmapID, dstDir string) error

BackupOne backs up an instance within the namespace to dstDir.

func (NameSpace) MMKVWithID

func (ns NameSpace) MMKVWithID(mmapID string, opts ...MMKVOption) (*MMKV, error)

MMKVWithID opens a read+write instance within the namespace (custom root dir).

func (NameSpace) Open

func (ns NameSpace) Open(mmapID string, opts ...Option) (*Reader, error)

Open opens an instance within the namespace.

func (NameSpace) RestoreOne

func (ns NameSpace) RestoreOne(mmapID, srcDir string) error

RestoreOne restores an instance within the namespace from srcDir.

func (NameSpace) RootDir

func (ns NameSpace) RootDir() string

RootDir returns the namespace root.

type Option

type Option func(*Reader)

Option configures a Reader.

func WithDecryptor

func WithDecryptor(d Decryptor) Option

WithDecryptor supplies a custom decryptor for encrypted files.

func WithEncryption

func WithEncryption(key []byte) Option

WithEncryption decrypts files written with an MMKV cryptKey. The AES width follows MMKV: a key longer than 16 bytes selects AES-256, otherwise AES-128; the key is truncated or zero-padded to 16/32 bytes. Pass the SAME key the writer used.

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader is a cgo-free read-only view of one MMKV instance.

func Open

func Open(rootDir, mmapID string, opts ...Option) (*Reader, error)

Open loads <rootDir>/<encodeFilePath(mmapID)> (+ ".crc") and keeps the reader transparently fresh (check-on-read; see package doc). POSIX-only.

func (*Reader) Close

func (r *Reader) Close() error

Close releases buffers, the mmap and the fd. Value slices from GetBytes/GetString become invalid afterwards.

func (*Reader) Contains

func (r *Reader) Contains(key string) bool

Contains reports whether key exists and is not expired.

func (*Reader) Err

func (r *Reader) Err() error

Err returns the last error from a best-effort reload, if any. Reads keep serving the last good snapshot when a reload fails.

func (*Reader) GetBool

func (r *Reader) GetBool(key string) (bool, bool)

func (*Reader) GetBytes

func (r *Reader) GetBytes(key string) ([]byte, bool)

GetBytes returns the value as a view into the reader's buffer (no copy); valid until the next reload/Close. Do not mutate it. Use GetBytesCopy for an independent slice (recommended in live mode).

func (*Reader) GetBytesCopy

func (r *Reader) GetBytesCopy(key string) ([]byte, bool)

GetBytesCopy returns an independent copy of the value.

func (*Reader) GetFloat32

func (r *Reader) GetFloat32(key string) (float32, bool)

func (*Reader) GetFloat64

func (r *Reader) GetFloat64(key string) (float64, bool)

func (*Reader) GetInt32

func (r *Reader) GetInt32(key string) (int32, bool)

func (*Reader) GetInt64

func (r *Reader) GetInt64(key string) (int64, bool)

func (*Reader) GetString

func (r *Reader) GetString(key string) (string, bool)

GetString returns the value as a zero-copy string view over the reader's buffer; valid until the next reload/Close, and the underlying bytes must not be mutated (e.g. via a GetBytes alias). The view aliases heap memory and is kept alive by the GC while held. Use GetStringCopy for an independent string (recommended for multi-goroutine live use).

func (*Reader) GetStringCopy

func (r *Reader) GetStringCopy(key string) (string, bool)

GetStringCopy returns the value as an independent string (a copy).

func (*Reader) GetUInt32

func (r *Reader) GetUInt32(key string) (uint32, bool)

func (*Reader) GetUInt64

func (r *Reader) GetUInt64(key string) (uint64, bool)

func (*Reader) Keys

func (r *Reader) Keys() []string

Keys returns all live (non-expired) keys, sorted.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer builds a plaintext MMKV instance from scratch and flushes it in a single full write-back — the same operation MMKV performs on its first write (empty dict → expandAndWriteBack → doFullWriteBack). It produces a file that the official C++ library and the read-only Reader both load: version=4 (Flag), sequence=1, no encryption, no expiration.

This is the Phase-A write seam. The incremental, lock-coordinated live MMKV type (append, transparent reload, multi-process) builds on the same encode/meta/memfile/flock foundation. A Writer is not safe for concurrent use and does not coordinate with other processes; use it to author or replace a file, not to co-write a live one. POSIX-only.

func NewWriter

func NewWriter(rootDir, mmapID string) *Writer

NewWriter starts a writer for <rootDir>/<encodeFilePath(mmapID)> (+ ".crc").

func (*Writer) Flush

func (w *Writer) Flush() error

Flush writes the data file and its ".crc" meta to disk via a full write-back, then msyncs both (data first, then meta — the order MMKV relies on for crash consistency).

func (*Writer) SetBool

func (w *Writer) SetBool(key string, v bool) *Writer

Typed setters return the Writer for chaining. The last value set for a key wins. An empty []byte/"" stores an empty value, which MMKV reads as present but zero-length (it is NOT a deletion — that is a separate operation).

func (*Writer) SetBytes

func (w *Writer) SetBytes(key string, v []byte) *Writer

func (*Writer) SetFloat32

func (w *Writer) SetFloat32(key string, v float32) *Writer

func (*Writer) SetFloat64

func (w *Writer) SetFloat64(key string, v float64) *Writer

func (*Writer) SetInt32

func (w *Writer) SetInt32(key string, v int32) *Writer

func (*Writer) SetInt64

func (w *Writer) SetInt64(key string, v int64) *Writer

func (*Writer) SetString

func (w *Writer) SetString(key, v string) *Writer

func (*Writer) SetStringSlice

func (w *Writer) SetStringSlice(key string, v []string) *Writer

func (*Writer) SetUInt32

func (w *Writer) SetUInt32(key string, v uint32) *Writer

func (*Writer) SetUInt64

func (w *Writer) SetUInt64(key string, v uint64) *Writer

Jump to

Keyboard shortcuts

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