The power of Java/.NET — the simplicity of Go.
Go is beautifully simple — but that simplicity comes with trade-offs. Verbosity is the first: operations that take one line in C# or Java often take five in Go. The second is ecosystem fragmentation: Go's culture of small, single-purpose packages means real-world projects end up stitching together dozens of third-party libraries, each written with a different philosophy, different naming conventions, different error-handling styles, and different testing approaches. The result? Your codebase looks like a patchwork of workarounds — not a cohesive system.
core solves this. It is the foundational package of the auk-go ecosystem — a series of packages designed to work together as a unified platform. When you build on core, every package in your project shares the same structure, the same conventions, and the same developer experience:
- No more verbosity — generic ternary helpers (
conditional/), nil-safe pointer conversions (typesconv/), one-line JSON pipelines (corejson/), and compute-once caching (coreonce/) eliminate boilerplate without hiding complexity. - No more magic strings — named constants (
constants/,coreindexes/), strongly-typed enums (issetter/), and semantic error types (errcore/) replace hardcoded values everywhere. - No more inconsistent tests — the built-in testing framework (
coretests/) providesCaseV1test cases,args.Mapfor semantic test inputs,ShouldBeEqual/ShouldBeEqualMapassertions, and the AAA (Arrange-Act-Assert) pattern out of the box. Separate your test data (_testcases.go) from test logic (_test.go) — every test reads the same way across the entire ecosystem. - No more interface guesswork — 100+ canonical interface contracts (
coreinterface/) following Go's-ersuffix convention (NameGetter,Serializer,IsEmptyChecker) ensure packages depend on behaviors, not concrete types. - No more unsafe nil panics — zero-nil safety is a first-class design principle. Functions return empty slices/maps instead of nil. Pointer-receiver methods include nil guards. Use
IsNull()/IsEmpty()/IsDefined()for explicit state checking.
The goal is simple: your code should look the same, read the same, and test the same — whether it's written by you, your teammate, or someone contributing from the other side of the world. core makes that possible by providing the shared foundation that every package in the ecosystem builds upon.
This library is not an academic exercise. It encapsulates 20 years of professional software engineering experience by Md. Alim Ul Karim — a system architect recognized as one of the top software architects globally. Alim has architected large-scale systems across enterprise, fintech, and distributed platforms, and brings that hard-won knowledge directly into every design decision in this framework. The patterns here — struct-as-namespace, one-file-per-function, interface-first design, newCreator factories — aren't arbitrary choices. They're battle-tested conventions refined over two decades of building production systems.
If something doesn't feel right — if a pattern seems wrong, an API is confusing, or you think there's a better approach — please tell us. Open an issue, start a discussion, or submit a merge request. We take all feedback seriously, treat criticism as a gift, and are committed to continuously improving this library for the community.
| Tool | Version |
|---|---|
| Go | 1.24+ (latest stable) |
| Git | ≥ 2.29 |
go get github.com/alimtvnetwork/core-v8git clone https://github.com/alimtvnetwork/core-v8.gitmake # build and run default CLI
make build # compile binary to build/cli
make run-tests # run integration tests
make run-server # start server entrypoint
make run-client # start client entrypoint
make run-sample # run sample/demo| Category | Packages | What You Get |
|---|---|---|
| Ternary helpers | conditional/ |
Generic If[T], IfFunc[T], IfSlice[T] — replaces missing ternary operator |
| Data structures | coredata/corestr/ |
Collection, Hashmap, Hashset, LinkedList, SimpleSlice |
| JSON | coredata/corejson/ |
Serialize.*, Deserialize.* — full JSON pipeline |
| Payload system | coredata/corepayload/ |
PayloadWrapper, Attributes, PayloadsCollection — structured data transport |
| Task info | coretaskinfo/ |
Info — metadata container with name, URLs, examples, secure/plain text modes |
| Error building | errcore/ |
Stack-traced errors, merge, expectations, Gherkins-style messages |
| File permissions | chmodhelper/ |
Parse, verify, and apply chmod on files and directories |
| Interfaces | coreinterface/ |
100+ canonical interface contracts (*Getter, *Checker, *Binder) |
| Converters | converters/ |
Type conversions: strings ↔ bytes, maps, pointers |
| Testing | coretests/ |
Assertion helpers, FuncWrap, CaseV1 for AAA-pattern tests |
| Regex | regexnew/ |
LazyRegex — compiles only on first use, with optional locking |
| Validators | corevalidator/ |
Line, slice, text, and range validators |
| Sorting | coresort/ |
Quick sort for strings and integers |
| Math | coremath/ |
Min/Max for all numeric types |
| Versioning | coreversion/ |
Semantic version data type (major.minor.patch) |
| Constants | constants/ |
OS line separators, empty values, capacity defaults |
| Generics | core.go, generic.go |
EmptySlicePtr[T], SlicePtrByCapacity[T], EmptyMapPtr[K,V] |
-
One file per function — each public function lives in its own
.gofile, named after the function. This keeps files small (~50-200 lines) and makes navigation instant. -
Struct-as-namespace — related operations are grouped on unexported struct types exposed via package-level
var. This gives you IDE autocompletion trees likecorejson.Serialize.ToString()orNew.PayloadWrapper.Empty(). -
Interface-first — all contracts are defined in
coreinterface/using Go's-ersuffix convention (e.g.,NameGetter,Csver,Serializer). Packages depend on interfaces, not concrete types. -
Zero-nil safety — functions return empty slices/maps instead of nil wherever possible. Pointer-receiver methods include nil guards. Use
IsNull()/IsEmpty()/IsDefined()for checking. -
Generics where clear — generic versions (
If[T],EmptySlicePtr[T],TypedErrorFunctionsExecuteResults[T]) exist alongside backward-compatible type-specific wrappers. -
Prefer value receivers (new code) — read-only methods use value receivers for simplicity. Pointer receivers are reserved for mutation, large structs, or interface satisfaction. See Coding Guidelines.
import "github.com/alimtvnetwork/core-v8/conditional"
// Generic (Go 1.22+)
result := conditional.If[int](true, 2, 7) // 2
name := conditional.If[string](len(s) > 0, s, "default")
// With lazy evaluation — only the chosen branch executes
val := conditional.IfFunc[string](expensive, func() string {
return computeValue()
}, func() string {
return "fallback"
})
// Slice ternary
items := conditional.IfSlice[int](hasItems, filled, empty)
// Legacy type-specific (still works, deprecated)
result := conditional.Int(true, 2, 7) // 2import "github.com/alimtvnetwork/core-v8"
ints := core.EmptySlicePtr[int]() // *[]int (empty, non-nil)
strs := core.SlicePtrByLength[string](10) // *[]string with len=10
m := core.EmptyMapPtr[string, int]() // *map[string]int (empty, non-nil)
capped := core.SlicePtrByCapacity[int](100) // *[]int with cap=100The payload system (coredata/corepayload/) is the primary data transport mechanism. Use PayloadWrapper to carry structured data between components:
import "github.com/alimtvnetwork/core-v8/coredata/corepayload"
// Create an empty payload
payload := corepayload.New.PayloadWrapper.Empty()
// Create with instruction
payload = corepayload.New.PayloadWrapper.UsingInstruction(
&corepayload.PayloadCreateInstruction{
Name: "user-create",
Identifier: "usr-123",
EntityType: "User",
Payloads: myStruct, // auto-serialized to JSON bytes
},
)
// Access data
fmt.Println(payload.PayloadName()) // "user-create"
fmt.Println(payload.IdString()) // "usr-123"
fmt.Println(payload.PayloadEntityType()) // "User"
// Deserialize dynamic payloads
var user User
err := payload.Deserialize(&user)
// Check for errors
if payload.HasError() {
log.Fatal(payload.Error())
}
// Attributes (key-value pairs, auth info, paging)
attrs := payload.InitializeAttributesOnNull()
attrs.AddOrUpdateString("role", "admin")
value, found := attrs.GetStringKeyValue("role") // "admin", true
// Set authentication info
payload.SetUser(&corepayload.User{Name: "alice"})
fmt.Println(payload.Username()) // "alice"
// Serialize/Deserialize the whole wrapper
jsonBytes, err := payload.Serialize()
restored, err := corepayload.New.PayloadWrapper.Deserialize(jsonBytes)coretaskinfo.Info holds metadata about tasks, errors, or operations — name, description, URLs, examples, and security flags:
import "github.com/alimtvnetwork/core-v8/coretaskinfo"
// Create with factory
info := coretaskinfo.New.Info.Default(
"user-validation",
"Validates user input fields",
"https://docs.example.com/validation",
)
// Create with examples
info = coretaskinfo.New.Info.Examples(
"email-format",
"RFC 5322 email validation",
"https://tools.ietf.org/html/rfc5322",
`validate("user@example.com")`,
`validate("bad@")`, // fails
)
// Secure vs plain text (controls payload logging)
secureInfo := coretaskinfo.New.Info.Secure.Default(
"password-reset", "Handles password reset", "",
)
fmt.Println(secureInfo.IsSecure()) // true
fmt.Println(secureInfo.IsPlainText()) // false
// Nil-safe access
var nilInfo *coretaskinfo.Info
fmt.Println(nilInfo.SafeName()) // "" (no panic)
fmt.Println(nilInfo.IsPlainText()) // true (default)
// Serialize to JSON
jsonStr := info.PrettyJsonString()
// Clone
copied := info.Clone()import "github.com/alimtvnetwork/core-v8/coredata/corejson"
type Example struct {
A string
B int
SomeMap map[string]string
}
from := &Example{A: "hello", B: 42, SomeMap: map[string]string{}}
to := &Example{}
// Deep copy via JSON
err := corejson.Deserialize.FromTo(from, to)
// Serialize to string
jsonStr, err := corejson.Serialize.ToString(from)
// jsonStr = `{"A":"hello","B":42,"SomeMap":{}}`
// Serialize to bytes
jsonBytes, err := corejson.Serialize.Raw(from)
// Deserialize from bytes
err = corejson.Deserialize.UsingBytes(jsonBytes, to)
// Pretty print
pretty := corejson.NewPtr(from).PrettyJsonString()import (
"github.com/alimtvnetwork/core-v8/coredata/corestr"
"github.com/alimtvnetwork/core-v8/constants"
)
values := []string{"hello", "world", "something"}
collection := corestr.NewCollectionPtrUsingStrings(&values, constants.Zero)
fmt.Println(collection.Length()) // 3
fmt.Println(collection.IsEmpty()) // false
collection.AddsLock("else")
fmt.Println(collection.Length()) // 4import "github.com/alimtvnetwork/core-v8/coredata/corestr"
hs := corestr.NewHashset(2)
hs.Add("alpha")
hs.Add("beta")
fmt.Println(hs.Length()) // 2
fmt.Println(hs.Has("alpha")) // trueimport "github.com/alimtvnetwork/core-v8/errcore"
// Rich error with stack trace
err := errcore.Expected.Error("config file", "/etc/app.conf")
// Merge multiple errors
combined := errcore.MergeErrors(err1, err2)
// Slice of error strings to single error
sliceErr := errcore.SliceToError([]string{"issue 1", "issue 2"})
// Type-based errors
err = errcore.CannotBeNilOrEmptyType.ErrorNoRefs("user input")The regexnew package provides thread-safe, lazy-compiled regular expressions with caching. Patterns compile only on first use and are stored in a global map for reuse.
import "github.com/alimtvnetwork/core-v8/regexnew"
// --- Package-level vars (init time, no goroutine contention) ---
// Use New.Lazy — no mutex lock needed at init
var digitRegex = regexnew.New.Lazy(`\d+`)
var emailRegex = regexnew.New.Lazy(`[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}`)
// --- Inside methods/goroutines (concurrent access) ---
// Use New.LazyLock — mutex-protected for thread safety
func validateInput(input string) bool {
lazy := regexnew.New.LazyLock(`^[a-z]+\d+$`)
return lazy.IsMatch(input)
}lazy := regexnew.New.LazyLock(`\d+`)
// Simple match
lazy.IsMatch("abc123") // true
lazy.IsMatch("no digits") // false
lazy.IsFailedMatch("abc123") // false (inverse of IsMatch)
// Byte matching
lazy.IsMatchBytes([]byte("abc123")) // true
lazy.IsFailedMatchBytes([]byte("letters")) // true
// First submatch extraction
lazy2 := regexnew.New.LazyLock(`(\d+)`)
match, invalid := lazy2.FirstMatchLine("abc 123 def 456")
// match = "123", invalid = false
// Match with error return (for validation pipelines)
err := lazy.MatchError("abc123") // nil (matched)
err = lazy.MatchError("letters") // error with descriptive messagelazy := regexnew.New.LazyLock(`\d+`)
// Explicit compile (returns cached after first call)
regex, err := lazy.Compile()
// Panic on compile failure
regex = lazy.CompileMust()
// State inspection
lazy.IsCompiled() // true after first Compile/Match
lazy.IsApplicable() // true if pattern is valid and compiled
lazy.IsDefined() // true if pattern is non-empty with compiler
lazy.HasError() // true if compile failed
lazy.HasAnyIssues() // true if nil, undefined, or compile error
lazy.Pattern() // returns the raw pattern string
lazy.String() // same as Pattern()// Direct create (cached in global map)
regex, err := regexnew.Create(`\d+`) // no lock, use in var init
regex, err = regexnew.CreateLock(`\d+`) // with lock, use in methods
regex = regexnew.CreateMust(`\d+`) // panics on error
// Conditional locking
regex, err = regexnew.CreateLockIf(true, `\d+`)
regex = regexnew.CreateMustLockIf(true, `\d+`)
// Create with applicability check
regex, err, isApplicable := regexnew.CreateApplicableLock(`\d+`)
// Quick match (creates regex + matches in one call)
regexnew.IsMatchLock(`\d+`, "abc123") // true
regexnew.IsMatchFailed(`\d+`, "abc123") // false
// Match with error (for validation)
err = regexnew.MatchError(`^hello$`, "hello") // nil
err = regexnew.MatchErrorLock(`^hello$`, "world") // error
// Custom match function
err = regexnew.MatchUsingFuncErrorLock(
`\d+`, "abc123",
func(re *regexp.Regexp, term string) bool {
return re.MatchString(term)
},
)
// Custom match + custom error
err = regexnew.MatchUsingCustomizeErrorFuncLock(
`\d+`, "abc123",
func(re *regexp.Regexp, term string) bool {
return re.MatchString(term)
},
func(pattern, term string, err error, re *regexp.Regexp) error {
return fmt.Errorf("custom: %s failed on %s", pattern, term)
},
)// Create two patterns atomically (single lock)
first, second := regexnew.New.LazyRegex.TwoLock(`\d+`, `[a-z]+`)
first.IsMatch("42") // true
second.IsMatch("abc") // true
// Create many patterns atomically
patterns := regexnew.New.LazyRegex.ManyUsingLock(`\d+`, `[a-z]+`, `\w+`)
patterns[`\d+`].IsMatch("123") // true
// Get all cached patterns
allPatterns := regexnew.New.LazyRegex.AllPatternsMap()
// Conditional lock
lazy := regexnew.New.LazyRegex.NewLockIf(true, `\d+`)import "github.com/alimtvnetwork/core-v8/regexnew"
// Ready-to-use lazy regex for common patterns
regexnew.WhitespaceFinderRegex.IsMatch("hello world") // true
regexnew.DollarIdentifierRegex.IsMatch("$MY_VAR") // true
regexnew.PrettyNameRegex.IsMatch("John Doe") // true
regexnew.FirstNumberAnyWhereCheckerRegex.IsMatch("version 42") // trueimport "github.com/alimtvnetwork/core-v8/coresort/strsort"
fruits := []string{"banana", "mango", "apple"}
strsort.Quick(&fruits) // [apple banana mango]
strsort.QuickDsc(&fruits) // [mango banana apple]The issetter package provides a byte-backed boolean type with 6 states for lazy evaluation, deferred decisions, and wildcard matching — going beyond Go's native true/false.
| Constant | Byte Value | Meaning | Use Case |
|---|---|---|---|
Uninitialized |
0 |
Not yet evaluated | Lazy fields, deferred config |
True |
1 |
Positive / yes / on | Standard boolean true |
False |
2 |
Negative / no / off | Standard boolean false |
Unset |
3 |
Explicitly cleared | User removed a setting |
Set |
4 |
Explicitly assigned | User confirmed a setting |
Wildcard |
5 |
Match anything | Filters, search patterns |
Logical grouping:
- Positive (
IsOn/IsAccept/IsSuccess):True,Set - Negative (
IsOff/IsReject/IsFailed):False,Unset - Indeterminate (
IsAsk/IsSkip):Uninitialized,Wildcard
import "github.com/alimtvnetwork/core-v8/issetter"
// Basic state checks
status := issetter.True
fmt.Println(status.HasInitialized()) // true
fmt.Println(status.IsOn()) // true (True or Set)
fmt.Println(status.IsOff()) // false
// Uninitialized = "not yet decided"
pending := issetter.Uninitialized
fmt.Println(pending.HasInitialized()) // false
fmt.Println(pending.IsUndefinedLogically()) // true
// Wildcard = "accept anything"
filter := issetter.Wildcard
fmt.Println(filter.WildcardApply(false)) // false (passes through input)
fmt.Println(filter.IsWildcardOrBool(true)) // true (wildcard always true)
// Lazy evaluation — only runs func on first call
var lazyFlag issetter.Value // starts as Uninitialized (0)
called := lazyFlag.LazyEvaluateBool(func() {
fmt.Println("computed!") // prints only once
})
fmt.Println(called) // true
fmt.Println(lazyFlag.IsTrue()) // true
// Convert between boolean ↔ set/unset semantics
v := issetter.True
fmt.Println(v.ToSetUnsetValue()) // Set
s := issetter.Set
fmt.Println(s.ToBooleanValue()) // True
// Ternary byte mapping
result := issetter.True.ToByteCondition(1, 0, 255)
fmt.Println(result) // 1See issetter/Value.go for all methods and issetter/README.md for the full API reference.
import "github.com/alimtvnetwork/core-v8/chmodhelper"
// Parse rwx string
rwx := chmodhelper.ExpandCharRwx("rwxr-xr--")
// Verify file permissions
isValid := chmodhelper.ChmodVerify.IsFileHasRwx(path, expectedRwx)import "github.com/alimtvnetwork/core-v8/corecsv"
// Any type implementing Csver interface gets CSV output
line := corecsv.DefaultCsv(myStruct) // "field1,field2,field3"import "github.com/alimtvnetwork/core-v8/conditional"
// Execute a set of functions and collect results
results, err := conditional.TypedErrorFunctionsExecuteResults[string](
true,
[]func() (string, error){
func() (string, error) { return "hello", nil },
func() (string, error) { return "world", nil },
},
nil, // false-branch functions (not used)
)
// results = ["hello", "world"], err = nilThis project follows the Arrange-Act-Assert (AAA) pattern with coretestcases.CaseV1, GoConvey assertions, and errcore.AssertDiffOnMismatch.
📖 Complete testing documentation:
/spec/testing-guidelines/— 8 detailed guides covering folder structure, all case types, args reference, assertion patterns, branch coverage, diagnostics, good-vs-bad examples, and custom case creation.📖 Full Testing Guidelines — comprehensive reference covering all assertion methods,
args.Mapusage, named test case variables,SliceValidator, comparison modes, custom test wrappers, panic testing, concurrency testing, anti-patterns, and a CaseV2 proposal.
tests/integratedtests/
├── mypkgtests/ # One directory per source package
│ ├── params.go # Reusable key constants for args.Map
│ ├── MyFunc_testcases.go # Test data — expectations only
│ ├── MyFunc_test.go # Test runner — assertions only
│ ├── MyStruct_NilReceiver_testcases.go # Nil-safety test data
│ ├── NilReceiver_test.go # Nil-safety test runner
│ └── helpers.go # Shared test-only structs/utilities
└── anotherpkgtests/
└── ...
Separation rules:
_testcases.go— ONLYvardeclarations, NOimport "testing", NOfunc Test__test.go— ONLY test functions with AAA comments, NO hardcoded expected valueshelpers.go— shared structs/utilities, NO test functions or test data
The workhorse for most tests. Supports string-based and map-based assertions.
_testcases.go:
package mypkgtests
import (
"github.com/alimtvnetwork/core-v8/coretests/args"
"github.com/alimtvnetwork/core-v8/coretests/coretestcases"
)
var validateEmailTestCases = []coretestcases.CaseV1{
{
Title: "ValidateEmail returns valid -- given well-formed email",
ArrangeInput: args.Map{
"email": "user@example.com",
},
ExpectedInput: args.Map{
"isValid": true,
"errorCount": 0,
},
},
{
Title: "ValidateEmail returns invalid -- given empty email",
ArrangeInput: args.Map{
"email": "",
},
ExpectedInput: args.Map{
"isValid": false,
"errorCount": 1,
},
},
}_test.go:
package mypkgtests
import (
"testing"
"github.com/alimtvnetwork/core-v8/coretests/args"
)
func Test_ValidateEmail_Verification(t *testing.T) {
for caseIndex, tc := range validateEmailTestCases {
// Arrange
input := tc.ArrangeInput.(args.Map)
email, _ := input.GetAsString("email")
// Act
result := validator.ValidateEmail(email)
actual := args.Map{
"isValid": result.IsValid,
"errorCount": len(result.Errors),
}
// Assert
tc.ShouldBeEqualMap(t, caseIndex, actual)
}
}For one-off tests, use a named standalone variable (not a slice) and *First assertion methods:
// _testcases.go
var concatMessageNilTestCase = coretestcases.CaseV1{
Title: "ConcatMessageWithErr nil error returns nil",
ArrangeInput: args.Map{
"message": "should not appear",
},
ExpectedInput: args.Map{
"isNil": true,
},
}
// _test.go
func Test_ConcatMessageWithErr_NilPassthrough(t *testing.T) {
tc := concatMessageNilTestCase
// Arrange
input := tc.ArrangeInput.(args.Map)
msg, _ := input.GetAsString("message")
// Act
result := errcore.ConcatMessageWithErr(msg, nil)
actual := args.Map{
"isNil": result == nil,
}
// Assert
tc.ShouldBeEqualMapFirst(t, actual)
}For testing pointer-receiver methods that must not panic on nil:
// _NilReceiver_testcases.go
var myStructNilSafeTestCases = []coretestcases.CaseNilSafe{
{
Title: "IsValid on nil returns false",
Func: (*MyStruct).IsValid,
Expected: results.ResultAny{
Value: "false",
Panicked: false,
},
},
{
Title: "HasKey on nil returns false",
Func: func(m *MyStruct) bool {
return m.HasKey("anything")
},
Expected: results.ResultAny{
Value: "false",
Panicked: false,
},
},
{
Title: "Clear on nil does not panic",
Func: (*MyStruct).Clear,
Expected: results.ResultAny{
Panicked: false,
},
CompareFields: []string{"panicked", "returnCount"},
},
}
// NilReceiver_test.go
func Test_MyStruct_NilReceiver(t *testing.T) {
for caseIndex, tc := range myStructNilSafeTestCases {
tc.ShouldBeSafe(t, caseIndex)
}
}For multi-field input → multi-field output with semantic keys and BDD fields (When, Given, Then):
// params.go
package mypkgtests
var params = struct {
pattern string
compareInput string
isDefined string
isApplicable string
isMatch string
}{
pattern: "pattern",
compareInput: "compareInput",
isDefined: "isDefined",
isApplicable: "isApplicable",
isMatch: "isMatch",
}
// _testcases.go
var lazyRegexTestCases = []coretestcases.MapGherkins{
{
Title: "New.Lazy matches word pattern",
When: "given a simple word pattern",
Input: args.Map{
params.pattern: "hello",
params.compareInput: "hello world",
},
Expected: args.Map{
params.isDefined: true,
params.isApplicable: true,
params.isMatch: true,
},
},
}
// _test.go
func Test_LazyRegex_New_Verification(t *testing.T) {
for caseIndex, tc := range lazyRegexTestCases {
// Arrange
pattern, _ := tc.Input.GetAsString(params.pattern)
compareInput, _ := tc.Input.GetAsString(params.compareInput)
// Act
lazy := regexnew.New.Lazy(pattern)
actual := args.Map{
params.isDefined: lazy.IsDefined(),
params.isApplicable: lazy.IsApplicable(),
params.isMatch: lazy.IsMatch(compareInput),
}
// Assert
tc.ShouldBeEqualMap(t, caseIndex, actual)
}
}| Condition | Use |
|---|---|
| Standard input → string output | CaseV1 + ShouldBeEqual |
| Standard input → multi-field output | CaseV1 + args.Map + ShouldBeEqualMap |
| Nil-receiver safety | CaseNilSafe + ShouldBeSafe |
| BDD with typed input/output | GenericGherkins[T1, T2] |
| Multi-field I/O with semantic keys | MapGherkins (alias for GenericGherkins[args.Map, args.Map]) |
| Domain-specific data extraction | Custom wrapper embedding CaseV1 |
| Method | Use When |
|---|---|
ShouldBeEqual(t, caseIndex, actual...) |
Loop-based, exact string match |
ShouldBeEqualFirst(t, actual...) |
Single test case (caseIndex=0) |
ShouldBeEqualMap(t, caseIndex, actualMap) |
Map-based comparison |
ShouldBeEqualMapFirst(t, actualMap) |
Single test case, map comparison |
ShouldContains(t, caseIndex, actual...) |
Substring match |
ShouldStartsWith(t, caseIndex, actual...) |
Prefix match |
ShouldBeSafe(t, caseIndex) |
Nil-receiver safety |
ShouldBeSafeFirst(t) |
Single nil-safety case |
- Separate test data —
_testcases.gofiles keep data out of test logic. - AAA comments — always label
// Arrange,// Act,// Assertsections. - Index tracking — always pass
caseIndexfor precise failure identification. - Native types in
args.Map— usetruenot"true", use5not"5". params.goconstants — never use raw string literals for map keys.- Descriptive titles —
"FuncName returns X -- given Y input"with--separator. - Multi-line
args.Map— for 2+ entries, each key-value pair on its own line.
When a method's behavior changes based on a bool parameter, create two separate methods with expressive names instead of one method with a flag. The caller's code reads like documentation.
// Add appends without locking — caller manages concurrency.
func (it *Collection) Add(str string) *Collection { ... }
// AddLock appends with mutex protection (thread-safe).
func (it *Collection) AddLock(str string) *Collection {
it.Lock()
defer it.Unlock()
return it.Add(str)
}// FmtDebug always logs.
func FmtDebug(format string, items ...any) { slog.Debug(fmt.Sprintf(format, items...)) }
// FmtDebugIf logs only when isDebug is true.
func FmtDebugIf(isDebug bool, format string, items ...any) {
if !isDebug { return }
FmtDebug(format, items...)
}func (it Status) IsValid() bool { return it != Invalid }
func (it Status) IsInvalid() bool { return it == Invalid }| Suffix | Purpose | Example |
|---|---|---|
*Lock |
Thread-safe (mutex) | Add → AddLock |
*If |
Conditional on is* bool |
FmtDebug → FmtDebugIf |
*Must |
Panics on error | Deserialize → DeserializeMust |
*NonEmpty |
Skips "" |
Add → AddNonEmpty |
*NonEmptyWhitespace |
Skips "" + whitespace |
Add → AddNonEmptyWhitespace |
*Trimmed* |
Trim then filter empty | TrimmedEachWords |
*Join |
Filter then join | NonEmptyJoin, NonWhitespaceJoin |
*Ptr |
Pointer return/accept | Json → JsonPtr |
ToPtr |
Value → pointer | (it Value) ToPtr() *Value |
*Strings / *Slice |
Variadic / slice input | AddNonEmptyStrings, AddNonEmptyStringsSlice |
*OrDefault |
Returns zero if missing | First → FirstOrDefault |
*OrDefaultWith |
Custom fallback | FirstOrDefaultWith(slice, "N/A") |
*New |
Returns new (no mutation) | AppendLineNew, MergeNew |
*Collection(s) |
Accepts collection type | AddCollection, AddCollections |
| (pair) | Opposite states | IsValid + IsInvalid |
Suffix order: Base + Filter + Type + Lock + If + Must (e.g., AddsNonEmptyPtrLock).
When multiple suffixes combine, they follow a fixed order: Base + Filter + Type + Lock + If + Must.
Add # base
AddNonEmpty # base + filter
AddNonEmptyStrings # base + filter + type
AddsNonEmptyPtrLock # base + filter + type + lock
CreateOrExistingLockIf # base + lock + if
DeserializeMust # base + must
ResultPtrMust # base + type + must
Combined methods delegate to simpler variants:
// AddNonEmptyLock = filter + lock — delegates to AddNonEmpty
func (it *Collection) AddNonEmptyLock(str string) *Collection {
it.Lock()
defer it.Unlock()
return it.AddNonEmpty(str)
}String methods provide filtering variants that silently skip invalid items:
// AddNonEmpty skips "" only
c.AddNonEmpty("") // skipped
c.AddNonEmpty("a") // added
// AddNonEmptyWhitespace skips "" and whitespace-only
c.AddNonEmptyWhitespace(" ") // skipped
c.AddNonEmptyWhitespace("a") // added
// Standalone slice functions
filtered := stringslice.NonEmptyStrings(input) // removes ""
filtered := stringslice.NonWhitespace(input) // removes "" and whitespace
filtered := stringslice.TrimmedEachWords(input) // trims + removes empty
// Conditional dispatch
result := stringslice.NonEmptyIf(shouldFilter, input)
// Filter + join
joined := stringslice.NonEmptyJoin(input, ", ")
joined := stringslice.NonWhitespaceJoin(input, "\n")See Coding Guidelines — Method Writing for full details and all patterns.
// Deserialize returns (*T, error). DeserializeMust panics via errcore.HandleErr.
func (it creator) Deserialize(bytes []byte) (*T, error) { ... }
func (it creator) DeserializeMust(bytes []byte) *T {
result, err := it.Deserialize(bytes)
errcore.HandleErr(err)
return result
}
// SerializeMust — nil-guard then delegate to Serialize
func (it *TypedPayloadWrapper[T]) SerializeMust() []byte {
if it == nil || it.Wrapper == nil {
panic(defaulterr.NilResult)
}
bytes, err := it.Serialize()
errcore.HandleErr(err)
return bytes
}Rules: (1) *Must always panics — never log, return a default, or swallow the error. (2) Use errcore.HandleErr(err) — not bare panic(err). (3) The *Must variant calls the error-returning version — never duplicate logic. (4) File naming: Deserialize.go / DeserializeMust.go. (5) Combine with *Ptr: ResultMust returns T, ResultPtrMust returns *T.
// Variadic is primary. *Slice companion accepts []T.
func (it *Collection) AddNonEmptyStrings(items ...string) *Collection { ... }
func (it *Collection) AddNonEmptyStringsSlice(items []string) *Collection {
return it.AddNonEmptyStrings(items...) // delegates via spread
}Fallback hierarchy:
| Suffix | Fallback | Example |
|---|---|---|
First |
Panics if empty | it.items[0] |
FirstOrDefault |
Returns zero value of T |
var zero T; return zero |
FirstOrDefaultWith(fallback) |
Returns caller-provided fallback | return fallback |
GetOrDefault(key, fallback) |
Map fallback | return defaultVal |
CreateOrExisting(name) |
Create-or-retrieve; returns (*T, bool) |
Cache/registry pattern |
func (it *Collection[T]) First() T { return it.items[0] } // panics
func (it *Collection[T]) FirstOrDefault() T { ... } // zero value
func FirstOrDefaultWith(s []string, d string) string { ... } // custom default
func (it *Hashmap[K,V]) GetOrDefault(key K, d V) V { ... } // map fallbackUsed when creating-or-retrieving from a cache/registry:
// CreateOrExisting returns an existing LazyRegex or creates a new one.
func (it *lazyRegexMap) CreateOrExisting(
patternName string,
) (lazyRegex *LazyRegex, isExisting bool) {
existing, found := it.items[patternName]
if found {
return existing, true
}
created := NewLazyRegex(patternName)
it.items[patternName] = created
return created, false
}
// CreateOrExistingLock — thread-safe variant (delegates to base).
func (it *lazyRegexMap) CreateOrExistingLock(
patternName string,
) (*LazyRegex, bool) {
it.Lock()
defer it.Unlock()
return it.CreateOrExisting(patternName)
}
// CreateOrExistingLockIf — combined: base + lock + if
func (it *lazyRegexMap) CreateOrExistingLockIf(
isLock bool,
patternName string,
) (*LazyRegex, bool) {
if isLock {
return it.CreateOrExistingLock(patternName)
}
return it.CreateOrExisting(patternName)
}File naming: CreateOrExisting.go / CreateOrExistingLock.go / CreateOrExistingLockIf.go.
// Deprecated: Use EmptySlicePtr[any]() instead.
func EmptyAnysPtr() *[]any { return EmptySlicePtr[any]() }Format: Always // Deprecated: Use X instead. — name the exact replacement, delegate to it, never delete.
Methods provide *Ptr variants for pointer return types and nil-safe pointer acceptance:
// Return pointer variant
func (it Version) Json() corejson.Result { return corejson.New(it) }
func (it Version) JsonPtr() *corejson.Result { return corejson.NewPtr(it) }
// Nil-safe checker variant
func IsEmpty(str string) bool { return str == "" }
func IsEmptyPtr(str *string) bool { return str == nil || *str == "" }
// Identity conversion
func (it Variant) ToPtr() *Variant { return &it }
func (it Version) NonPtr() Version { return it }Rules: (1) *Ptr checkers treat nil as empty/absent. (2) Pointer-receiver *Ptr methods must guard nil. (3) Each variant in its own file (IsEmpty.go / IsEmptyPtr.go).
See Coding Guidelines — Pointer Variants for all five patterns.
All interfaces in coreinterface/ follow Go's -er suffix convention:
| Pattern | Example | Purpose |
|---|---|---|
*Getter |
NameGetter, ValueGetter |
Read a single value |
*Checker |
HasErrorChecker, IsEmptyChecker |
Boolean state check |
*Binder |
ContractsBinder, AttributesBinder |
Compose multiple interfaces |
*er |
Csver, Serializer, Stringer |
Action performer |
| Problem | Solution |
|---|---|
go get fails with auth error |
Add SSH key to GitLab or use access token: git config url."https://oauth2:TOKEN@gitlab.com".insteadOf "https://gitlab.com" |
go mod tidy reports version conflicts |
Ensure go.mod specifies go 1.24 and run go mod tidy |
| Tests fail after clone | Run make run-tests — some tests require the full module graph |
| Import path has typo | Known: convertinteranl → convertinternal, refeflectcore → reflectcore (being fixed) |
core/
├── core.go, generic.go # Root package — generic slice/map factories
├── makefile # Build, test, run targets
├── go.mod / go.sum # Go module definition (Go 1.24+)
│
├── conditional/ # Generic ternary helpers (If[T], IfFunc[T], IfSlice[T])
├── constants/ # OS line separators, empty values, capacity defaults
├── converters/ # Type conversions: strings ↔ bytes, maps, pointers
│
├── coredata/ # Data structures & serialization
│ ├── coreapi/ # API request/response types (Generic + Typed[T])
│ ├── coredynamic/ # Dynamic type wrappers, Collection[T], SimpleRequest
│ ├── coregeneric/ # Generic Collection, Hashset, Hashmap, LinkedList
│ ├── corejson/ # JSON serialize/deserialize pipeline
│ ├── corepayload/ # PayloadWrapper — structured data transport
│ ├── corestr/ # String Collection, Hashset, Hashmap, ValidValue
│ ├── coreonce/ # Lazy-evaluated cached values (StringOnce, IntegerOnce)
│ ├── corerange/ # Range types (int, byte)
│ └── stringslice/ # Slice utilities for []string
│
├── coreinterface/ # 100+ canonical interface contracts
│ ├── enuminf/ # Enum interfaces
│ ├── errcoreinf/ # Error wrapper interfaces
│ ├── serializerinf/ # Serializer/deserializer interfaces
│ └── baseactioninf/ # Action/execution interfaces
│
├── corefuncs/ # Function type definitions (generic + legacy)
├── coretaskinfo/ # Task metadata (Info, ExcludingOptions)
├── corevalidator/ # Line, slice, text, range validators
├── coreversion/ # Semantic versioning (major.minor.patch)
├── coremath/ # Min/Max for all numeric types
├── coresort/ # Quick sort for strings and integers
├── corecsv/ # CSV formatting utilities
│
├── errcore/ # Rich error construction with stack traces
├── chmodhelper/ # File permission parsing and verification
├── regexnew/ # Lazy-compiled regex with thread-safe caching
├── issetter/ # 6-valued boolean (Uninitialized/True/False/Unset/Set/Wildcard)
│
├── coretests/ # Testing helpers, FuncWrap, assertion wrappers
│ ├── args/ # FuncWrap argument types (OneFunc, TwoFunc, etc.)
│ └── coretestcases/ # CaseV1 test case definitions
│
├── tests/integratedtests/ # All unit/integration tests (per-package subdirs)
│
├── internal/ # Internal packages (not importable externally)
│ ├── convertinternal/ # Low-level type conversion
│ ├── reflectinternal/ # Reflection helpers
│ └── strutilinternal/ # String utility internals
│
├── # codegen/ removed (v1.6.0) — was test boilerplate generation
├── cmd/ # CLI entrypoints (main, server, client, sample)
│
├── spec/ # Architecture docs, coding guidelines, issue tracking
│ ├── 01-app/ # Core specs and conventions
│ └── 13-app-issues/ # Known issues and improvement backlog
│
└── assets/ # Logo and static assets
Each major package has its own README with detailed type hierarchies, usage examples, and method references:
| Package | README |
|---|---|
coredata/ |
README.md — Umbrella index for all data sub-packages |
coredata/coregeneric/ |
README.md — Generic Collection, Hashset, Hashmap, LinkedList |
coredata/corestr/ |
README.md — String Collection, Hashmap, Hashset, ValidValue |
coredata/corejson/ |
README.md — JSON serialization pipeline |
coredata/coredynamic/ |
README.md — Dynamic wrappers, Collection[T], TypedSimpleRequest/Result |
coredata/corepayload/ |
README.md — PayloadWrapper, TypedPayloadWrapper[T], Attributes |
coredata/coreapi/ |
README.md — Typed API request/response |
coredata/coreonce/ |
README.md — Lazy-evaluated cached values |
coredata/corerange/ |
README.md — Range types (int, byte) |
coredata/stringslice/ |
README.md — Slice utilities for []string |
| Package | README |
|---|---|
coreinterface/ |
README.md — Shared interface contracts |
coreinterface/enuminf/ |
README.md — Enum interface contracts |
coreinterface/errcoreinf/ |
README.md — Error core interface contracts |
coreinterface/loggerinf/ |
README.md — Logger interface contracts |
coreinterface/serializerinf/ |
README.md — Serializer interface contracts |
| Package | README |
|---|---|
coreimpl/ |
README.md — Core implementations (enumimpl) |
| Package | README |
|---|---|
conditional/ |
README.md — Generic ternary & nil-safe helpers |
constants/ |
README.md — Shared constants & capacity values |
converters/ |
README.md — Type conversion utilities |
corefuncs/ |
README.md — Function type definitions & wrappers |
coretaskinfo/ |
README.md — Task metadata container |
corevalidator/ |
README.md — Text, line & slice validators |
coremath/ |
README.md — Min/Max for all numeric types |
coresort/ |
README.md — Quick sort for strings and integers |
| Package | README |
|---|---|
errcore/ |
README.md — Error construction & formatting |
anycmp/ |
README.md — Any-type quick comparison |
isany/ |
README.md — Reflection-based type & null checking |
| Package | README |
|---|---|
chmodhelper/ |
README.md — File permission management |
regexnew/ |
README.md — Lazy-compiled regex |
issetter/ |
README.md — Multi-valued boolean enum |
| Package | README |
|---|---|
coretests/ |
README.md — Test utilities & assertions |
| Package | README |
|---|---|
cmd/ |
README.md — CLI entrypoints |
For the complete folder-by-folder breakdown, see the Folder Map.
The corefuncs/ package defines reusable function signatures and structural wrappers — generic [T] types first, with any-based legacy types for backward compatibility. See the full corefuncs README for complete documentation.
import "github.com/alimtvnetwork/core-v8/corefuncs"
// Generic function types (type-safe, recommended)
var transform corefuncs.InOutFuncOf[string, int] = func(s string) int {
return len(s)
}
// Generic wrappers — named error reporting + ActionFunc conversion
wrapper := corefuncs.NewInOutErrWrapper[string, int](
"parse-age",
func(s string) (int, error) { return strconv.Atoi(s) },
)
age, err := wrapper.Exec("25") // strongly typed
errFn := wrapper.AsActionReturnsErrorFunc("25") // convert to ActionReturnsErrorFunc
legacy := wrapper.ToLegacy() // backward compatible InOutErrFuncWrapper
// ResultDelegatingFuncWrapperOf[T] — typed unmarshal/reflect targets
unmarshalWrapper := corefuncs.NewResultDelegatingWrapper[*User](
"json-unmarshal",
func(target *User) error { return json.Unmarshal(data, target) },
)
// Legacy wrappers via New creator
actionWrapper := corefuncs.New.ActionErr("cleanup", cleanupFunc)
successWrapper := corefuncs.New.IsSuccess("healthcheck", pingFunc)The coredata/coreapi/ package provides both dynamic (any-based) and strongly-typed ([T]) API types:
import "github.com/alimtvnetwork/core-v8/coredata/coreapi"
// --- Typed (Generic) API — compile-time type safety ---
// Strongly typed request
type UserCreateInput struct {
Name string
Email string
}
req := coreapi.NewTypedRequestIn[UserCreateInput](
&coreapi.RequestAttribute{
Url: "/api/users",
ResourceName: "User",
ActionName: "Create",
IsValid: true,
},
UserCreateInput{Name: "Alice", Email: "alice@example.com"},
)
// Access is fully typed — no assertions needed
fmt.Println(req.Request.Name) // "Alice"
fmt.Println(req.Request.Email) // "alice@example.com"
// Strongly typed response
type UserOutput struct {
ID int
Name string
}
resp := coreapi.NewTypedResponse[UserOutput](
&coreapi.ResponseAttribute{IsValid: true, HttpCode: 200},
UserOutput{ID: 1, Name: "Alice"},
)
fmt.Println(resp.Response.ID) // 1
// Clone (deep copy)
clone := req.Clone()
// Convert to legacy dynamic type for backward compatibility
legacyReq := req.ToGenericRequestIn()
// --- Legacy Dynamic API (still supported) ---
dynamicReq := &coreapi.GenericRequestIn{
Attribute: &coreapi.RequestAttribute{IsValid: true},
Request: map[string]string{"key": "value"}, // any type
}import "github.com/alimtvnetwork/core-v8/coredata/corejson"
// --- Serialization ---
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email,omitempty"`
}
user := User{Name: "Alice", Age: 30}
// To JSON string
jsonStr, err := corejson.Serialize.ToString(user)
// `{"name":"Alice","age":30}`
// To JSON bytes
jsonBytes, err := corejson.Serialize.Raw(user)
// Pretty print
result := corejson.NewPtr(user)
pretty := result.PrettyJsonString()
// --- Deserialization ---
var restored User
err = corejson.Deserialize.UsingBytes(jsonBytes, &restored)
// Deep copy via JSON round-trip
source := User{Name: "Bob", Age: 25}
target := User{}
err = corejson.Deserialize.FromTo(source, &target)
// --- Result type (wraps bytes + error) ---
result = corejson.NewPtr(user)
fmt.Println(result.HasError()) // false
fmt.Println(result.HasIssuesOrEmpty()) // false
bytes := result.SafeValues() // []byte — safe, never nil
// Error handling
invalidResult := corejson.New(make(chan int)) // can't serialize channels
fmt.Println(invalidResult.HasError()) // true
fmt.Println(invalidResult.ErrorString()) // marshaling error messageThe coretests/ package provides assertion helpers and test-case structures for the AAA pattern:
import (
"testing"
"github.com/alimtvnetwork/core-v8/coretests"
"github.com/alimtvnetwork/core-v8/coretests/coretestcases"
"github.com/alimtvnetwork/core-v8/coretests/args"
)
// === Test Cases (in _testcases.go) ===
var uppercaseTestCases = []coretestcases.CaseV1{
{
Title: "converts lowercase to uppercase",
ArrangeInput: args.Map{
"actual": "hello",
"expect": "HELLO",
},
ExpectedInput: []string{"HELLO"},
},
{
Title: "handles empty string",
ArrangeInput: args.Map{
"actual": "",
"expect": "",
},
ExpectedInput: []string{""},
},
}
// === Test Runner (in _test.go) ===
func Test_ToUpper(t *testing.T) {
for caseIndex, tc := range uppercaseTestCases {
// Arrange
input := tc.ArrangeInput.(args.Map)
actual := input["actual"].(string)
// Act
result := strings.ToUpper(actual)
// Assert
lines := coretests.GetAssert.ToStrings(result)
tc.ShouldBeEqual(t, caseIndex, lines...)
}
}
// === FuncWrap — reflection-based test wrappers ===
// Wraps a function for automatic input/output assertion
wrap := args.NewOneFunc(
myFunc, // function under test
"expected output", // expected result
)
fmt.Println(wrap.WorkFunc) // the function reference
fmt.Println(wrap.Expect) // "expected output"
// === GetAs* assertion helpers ===
assert := coretests.GetAssert
lines := assert.ToStrings(result) // any → []string for comparison
str := assert.ToString(result) // any → stringDetailed architecture and conventions documentation for AI agents and contributors:
External packages used:
github.com/smartystreets/goconvey— BDD-style testinggithub.com/smarty/assertions— assertion librarygolang.org/x/tools— Go tooling support
- Go Slice Tricks Cheat Sheet
- SliceTricks · golang/go Wiki
- Calling a method on a nil struct pointer
- Array of pointers to JSON
- Md. Alim Ul Karim — Creator & Lead Architect. System architect with 20+ years of professional software engineering experience across enterprise, fintech, and distributed systems. Recognized as one of the top software architects globally. Alim's architectural philosophy — consistency over cleverness, convention over configuration — is the driving force behind every design decision in this framework.
- Riseup Asia LLC (Top Leading Software Company in WY) (2026)
MIT License — Copyright (c) 2020–2026. See LICENSE...
