A collection of shared utilities and entities for Global Names Architecture Go projects.
- User-Friendly Error Handling: Terminal-colorized error messages with clean output
- Generic Utilities: Type-safe Map, Filter, and other collection operations
- Channel Operations: Chunk channel data into manageable batches
- Version Comparison: Semantic version comparison utilities
- UTF-8 Handling: Fix and normalize UTF-8 strings
- Domain Entities: Shared types for taxonomic name verification, reconciliation, and matching
go get github.com/gnames/gnlibThe error handling system allows you to create errors that produce clean, colorized output for the terminal, while preserving the underlying error details for logging.
Use FormatMessage as a standalone function for any message formatting needs:
package main
import (
"fmt"
"github.com/gnames/gnlib"
)
func main() {
// Format a message with tags and variables
msg := gnlib.FormatMessage(
"Processing <title>%s</title>: <em>%d</em> items found",
[]any{"data.csv", 42},
)
fmt.Println(msg)
// Output (with colors): Processing data.csv: 42 items found
}Create custom error types that embed MessageBase for more structured error handling:
package main
import (
"errors"
"fmt"
"os"
"github.com/gnames/gnlib"
)
func main() {
// Create a custom error type
type FileError struct {
error
gnlib.MessageBase
}
// Create a new error with a format string and variables
base := gnlib.NewMessage(
"<warning>Could not process file '%s'</warning>",
[]any{"important.txt"},
)
err := FileError{
error: errors.New("file processing failed"),
MessageBase: base,
}
// The UserMessage() method returns the formatted, colorized string
fmt.Fprintln(os.Stdout, err.UserMessage())
// Example of wrapping the error
wrappedErr := fmt.Errorf("operation failed: %w", err)
// You can inspect the error chain to get the user-friendly message
var gnErr gnlib.Error
if errors.As(wrappedErr, &gnErr) {
fmt.Fprintln(os.Stdout, "---")
fmt.Fprintln(os.Stdout, "Message from wrapped error:")
fmt.Fprintln(os.Stdout, gnErr.UserMessage())
}
}This will produce the following output (with colors in the terminal):
Could not process file 'important.txt'
---
Message from wrapped error:
Could not process file 'important.txt'
Both FormatMessage and UserMessage() recognize the following tags for styling terminal output:
<title>...</title>: Renders text in green.<warning>...</warning>: Renders text in red.<em>...</em>: Renders text in yellow.
The library provides type-safe generic functions for common operations:
package main
import (
"fmt"
"github.com/gnames/gnlib"
)
func main() {
// Map transforms a slice
numbers := []int{1, 2, 3, 4, 5}
doubled := gnlib.Map(numbers, func(n int) int { return n * 2 })
fmt.Println(doubled) // [2 4 6 8 10]
// Filter returns elements matching a condition
evens := gnlib.FilterFunc(numbers, func(n int) bool { return n%2 == 0 })
fmt.Println(evens) // [2 4]
// SliceMap creates a lookup map from a slice
fruits := []string{"apple", "banana", "cherry"}
fruitMap := gnlib.SliceMap(fruits)
fmt.Println(fruitMap["banana"]) // 1
}Process channel data in chunks:
package main
import (
"context"
"fmt"
"github.com/gnames/gnlib"
)
func main() {
input := make(chan int)
go func() {
for i := 1; i <= 10; i++ {
input <- i
}
close(input)
}()
chunked := gnlib.ChunkChannel(context.Background(), input, 3)
for chunk := range chunked {
fmt.Println(chunk)
}
// Output:
// [1 2 3]
// [4 5 6]
// [7 8 9]
// [10]
}Compare semantic versions:
package main
import (
"fmt"
"github.com/gnames/gnlib"
)
func main() {
result := gnlib.CmpVersion("v1.2.3", "v1.2.4")
fmt.Println(result) // -1 (first is less than second)
result = gnlib.CmpVersion("v2.0.0", "v1.9.9")
fmt.Println(result) // 1 (first is greater than second)
result = gnlib.CmpVersion("v1.0.0", "v1.0.0")
fmt.Println(result) // 0 (versions are equal)
}Fix invalid UTF-8 sequences and normalize strings:
package main
import (
"fmt"
"github.com/gnames/gnlib"
)
func main() {
// Replaces invalid UTF-8 with U+FFFD and normalizes to NFC
fixed := gnlib.FixUtf8("invalid\xc3\x28utf8")
fmt.Println(fixed)
}The library includes shared entity types for taxonomic name processing:
ent/verifier: Types for taxonomic name verification resultsent/reconciler: Types for name reconciliation and manifestsent/matcher: Types for name matching operationsent/nomcode: Nomenclatural code enumerationsent/gnml: Global Names Markup Language typesent/gnvers: Version information types
See the API documentation for details on these packages.
Released under the MIT License. See LICENSE file for details.