{"id":42081458,"url":"https://github.com/enetx/g","last_synced_at":"2026-03-08T21:27:26.353Z","repository":{"id":228838717,"uuid":"774230549","full_name":"enetx/g","owner":"enetx","description":"Functional programming framework for Go.","archived":false,"fork":false,"pushed_at":"2026-01-31T11:17:44.000Z","size":1528,"stargazers_count":42,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-31T23:46:43.757Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://enetx.surf","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/enetx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-03-19T07:14:52.000Z","updated_at":"2026-01-31T11:16:43.000Z","dependencies_parsed_at":"2024-04-14T20:23:43.855Z","dependency_job_id":"9defd877-c4a5-488a-a45d-88f6a4817530","html_url":"https://github.com/enetx/g","commit_stats":null,"previous_names":["enetx/g"],"tags_count":202,"template":false,"template_full_name":null,"purl":"pkg:github/enetx/g","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enetx%2Fg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enetx%2Fg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enetx%2Fg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enetx%2Fg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/enetx","download_url":"https://codeload.github.com/enetx/g/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/enetx%2Fg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29199519,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T14:35:27.868Z","status":"ssl_error","status_checked_at":"2026-02-07T14:25:51.081Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-26T10:01:39.572Z","updated_at":"2026-03-08T21:27:26.344Z","avatar_url":"https://github.com/enetx.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://user-images.githubusercontent.com/65846651/229838021-741ff719-8c99-45f6-88d2-1a32927bd863.png\"\u003e\n\u003c/p\u003e\n\n# g - Functional programming framework for Go.\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/enetx/g.svg)](https://pkg.go.dev/github.com/enetx/g)\n[![Go Report Card](https://goreportcard.com/badge/github.com/enetx/g)](https://goreportcard.com/report/github.com/enetx/g)\n[![Coverage Status](https://coveralls.io/repos/github/enetx/g/badge.svg?branch=main\u0026service=github)](https://coveralls.io/github/enetx/g?branch=main)\n[![Go](https://github.com/enetx/g/actions/workflows/go.yml/badge.svg)](https://github.com/enetx/g/actions/workflows/go.yml)\n[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/enetx/g)\n\n```bash\ngo get github.com/enetx/g\n```\n\nRequires **Go 1.24+**\n\n---\n\n## Quick Start\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com/enetx/g\"\n)\n\nfunc main() {\n    // Slice with functional operations\n    g.SliceOf(1, 2, 3, 4, 5).\n        Iter().\n        Filter(func(x int) bool { return x%2 == 0 }).\n        Map(func(x int) int { return x * x }).\n        Collect().\n        Println() // Slice[4, 16]\n\n    // Safe map access with Option\n    m := g.NewMap[string, int]()\n    m.Insert(\"key\", 42)\n\n    value := m.Get(\"key\").UnwrapOr(0)\n    fmt.Println(value) // 42\n\n    // Result for error handling\n    result := g.String(\"123\").TryInt()\n    if result.IsOk() {\n        fmt.Println(result.Unwrap()) // 123\n    }\n}\n```\n\n---\n\n## Navigation\n\n| Core | Collections | Sync | Types |\n|:----:|:-----------:|:----:|:-----:|\n| [Option](#option) | [Slice](#slice) | [Mutex](#mutex) | [String](#string) |\n| [Result](#result) | [Map](#map) | [RwLock](#rwlock) | [Int/Float](#int--float) |\n| [Iterators](#iterators) | [Set](#set) | [Pool](#pool) | [Bytes](#bytes) |\n| | [Heap](#heap) | | [File/Dir](#file--directory) |\n| | [Deque](#deque) | | |\n\n---\n\n## Option\n\nSafe nullable values: `Some(value)` or `None`.\n\n```go\nopt := g.Some(42)           // Some(42)\nnone := g.None[int]()       // None\n\nopt.IsSome()                // true\nopt.Unwrap()                // 42 (panics if None)\nopt.UnwrapOr(0)             // 42 (returns default if None)\nopt.UnwrapOrDefault()       // 42 (returns zero value if None)\n\n// From map lookup\nv, ok := myMap[key]\nopt := g.OptionOf(v, ok)\n\n// Chaining\ng.Some(5).Then(func(x int) g.Option[int] {\n    return g.Some(x * 2)\n}) // Some(10)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eAll Option Methods\u003c/b\u003e\u003c/summary\u003e\n\n| Method | Description |\n|--------|-------------|\n| `IsSome()` | Returns true if contains value |\n| `IsNone()` | Returns true if empty |\n| `Some()` | Returns value (same as Unwrap) |\n| `Unwrap()` | Returns value, panics if None |\n| `UnwrapOr(default)` | Returns value or default |\n| `UnwrapOrDefault()` | Returns value or zero value |\n| `UnwrapOrElse(fn)` | Returns value or result of fn |\n| `Expect(msg)` | Returns value, panics with msg if None |\n| `Then(fn)` | Transforms value if Some |\n| `Option()` | Returns (value, bool) |\n| `Take()` | Takes value, leaves None |\n| `Filter(fn)` | Returns None if predicate fails |\n\n\u003c/details\u003e\n\n---\n\n## Result\n\nSuccess (`Ok`) or failure (`Err`) with error.\n\n```go\nok := g.Ok(42)                              // Ok(42)\nerr := g.Err[int](errors.New(\"failed\"))     // Err\n\nok.IsOk()                   // true\nok.Unwrap()                 // 42\nerr.UnwrapOr(0)             // 0\n\n// From standard (value, error) pattern\nresult := g.ResultOf(strconv.Atoi(\"42\"))    // Ok(42)\nresult := g.String(\"42\").TryInt()           // Ok(42)\n\n// Chaining\ng.Ok(10).Then(func(x int) g.Result[int] {\n    return g.Ok(x * 2)\n}) // Ok(20)\n\n// Convert to Option (discards error)\nopt := result.Option()      // Some(42)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eAll Result Methods\u003c/b\u003e\u003c/summary\u003e\n\n| Method | Description |\n|--------|-------------|\n| `IsOk()` | Returns true if success |\n| `IsErr()` | Returns true if error |\n| `Ok()` | Returns value (same as Unwrap) |\n| `Err()` | Returns error |\n| `Unwrap()` | Returns value, panics if Err |\n| `UnwrapOr(default)` | Returns value or default |\n| `UnwrapOrDefault()` | Returns value or zero value |\n| `UnwrapOrElse(fn)` | Returns value or result of fn |\n| `Expect(msg)` | Returns value, panics with msg |\n| `Then(fn)` | Chains operation if Ok |\n| `ThenOf(fn)` | Chains (T, error) function |\n| `MapErr(fn)` | Transforms error if Err |\n| `Option()` | Converts to Option |\n| `Result()` | Returns (value, error) |\n\n\u003c/details\u003e\n\n---\n\n## Slice\n\nExtended slice with 90+ methods.\n\n```go\ns := g.SliceOf(1, 2, 3, 4, 5)\ns := g.NewSlice[int](10)        // with capacity\n\ns.Len()                         // Int(5)\ns.Get(0)                        // Some(1)\ns.Get(100)                      // None (safe!)\ns.Last()                        // Some(5)\ns.Contains(3)                   // true\n\ns.Push(6, 7)                    // append in place\ns.Pop()                         // Some(7)\ns.Clone()                       // safe copy\n\n// Sorting\ns.SortBy(cmp.Cmp)               // ascending\ns.Reverse()                     // in place\ns.Shuffle()                     // random order\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eAll Slice Methods\u003c/b\u003e\u003c/summary\u003e\n\n| Category | Methods |\n|----------|---------|\n| **Access** | `Get`, `Last`, `First`, `Random`, `RandomSample` |\n| **Modify** | `Set`, `Push`, `Pop`, `Insert`, `Remove`, `Clear` |\n| **Search** | `Contains`, `ContainsBy`, `Index`, `IndexBy` |\n| **Transform** | `Clone`, `Reverse`, `Shuffle`, `SortBy`, `SubSlice` |\n| **Convert** | `Iter`, `Heap`, `Std` |\n| **Info** | `Len`, `Cap`, `IsEmpty` |\n\n\u003c/details\u003e\n\n---\n\n## Map\n\nExtended map with Entry API.\n\n```go\nm := g.NewMap[string, int]()\n\nm.Insert(\"a\", 1)                // insert value\nm.Get(\"a\")                      // Some(1)\nm.Get(\"x\")                      // None\nm.Contains(\"a\")                 // true\nm.Remove(\"a\")                   // remove\n\nm.Keys()                        // Slice of keys\nm.Values()                      // Slice of values\n```\n\n### Entry API\n\nEfficient update without multiple lookups:\n\n```go\n// Insert if absent\nm.Entry(\"counter\").OrInsert(0)\n\n// Update if present, insert if absent\nm.Entry(\"counter\").AndModify(func(v *int) { *v++ }).OrInsert(1)\n\n// Lazy initialization\nm.Entry(\"key\").OrInsertWith(func() int {\n    return expensiveComputation()\n})\n```\n\n**Word frequency example:**\n```go\nwords := g.SliceOf(\"apple\", \"banana\", \"apple\", \"cherry\", \"banana\", \"apple\")\nfreq := g.NewMap[string, int]()\n\nfor _, word := range words {\n    freq.Entry(word).AndModify(func(v *int) { *v++ }).OrInsert(1)\n}\n// {\"apple\": 3, \"banana\": 2, \"cherry\": 1}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eEntry Pattern Matching\u003c/b\u003e\u003c/summary\u003e\n\n```go\nswitch e := m.Entry(\"key\").(type) {\ncase g.OccupiedEntry[string, int]:\n    fmt.Println(\"Exists:\", e.Get())\n    e.Insert(newValue)      // replace\n    e.Remove()              // delete\ncase g.VacantEntry[string, int]:\n    e.Insert(defaultValue)  // insert\n}\n```\n\n\u003c/details\u003e\n\n---\n\n## Set\n\nCollection of unique elements.\n\n```go\ns := g.SetOf(1, 2, 3)\ns.Insert(4)                     // add\ns.Remove(1)                     // remove\ns.Contains(2)                   // true\n```\n\n### Set Operations\n\n```go\na := g.SetOf(1, 2, 3, 4)\nb := g.SetOf(3, 4, 5, 6)\n\na.Union(b).Collect()            // {1, 2, 3, 4, 5, 6}\na.Intersection(b).Collect()     // {3, 4}\na.Difference(b).Collect()       // {1, 2}\na.SymmetricDifference(b).Collect() // {1, 2, 5, 6}\n\na.Subset(b)                     // false\na.Superset(b)                   // false\n```\n\n---\n\n## Heap\n\nPriority queue (binary heap).\n\n```go\nimport \"github.com/enetx/g/cmp\"\n\n// Min-heap (smallest first)\nh := g.NewHeap(cmp.Cmp[int])\nh.Push(5, 3, 8, 1, 9)\n\nh.Peek()                        // Some(1)\nh.Pop()                         // Some(1)\nh.Pop()                         // Some(3)\n\n// Max-heap (largest first)\nmaxH := g.NewHeap(func(a, b int) cmp.Ordering {\n    return cmp.Cmp(b, a)\n})\n\n// From slice\nheap := g.SliceOf(5, 3, 8, 1).Heap(cmp.Cmp)\n```\n\n---\n\n## Deque\n\nDouble-ended queue (ring buffer). O(1) at both ends.\n\n```go\ndq := g.NewDeque[int]()\ndq := g.DequeOf(1, 2, 3)\n\ndq.PushFront(0)                 // add to front\ndq.PushBack(4)                  // add to back\n\ndq.Front()                      // Some(0)\ndq.Back()                       // Some(4)\n\ndq.PopFront()                   // Some(0)\ndq.PopBack()                    // Some(4)\n\ndq.Get(1)                       // element at index\ndq.Len()                        // length\ndq.IsEmpty()                    // true/false\n```\n\n---\n\n## Iterators\n\nFunctional operations on sequences.\n\n```go\ng.SliceOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).\n    Iter().\n    Filter(func(x int) bool { return x%2 == 0 }).\n    Map(func(x int) int { return x * x }).\n    Take(3).\n    Collect()\n// [4, 16, 36]\n```\n\n### Common Patterns\n\n```go\n// Chain iterators\ng.SliceOf(1, 2).Iter().Chain(g.SliceOf(3, 4).Iter()).Collect()\n// [1, 2, 3, 4]\n\n// Sum with Fold\ng.SliceOf(1, 2, 3, 4, 5).Iter().Fold(0, func(acc, x int) int { return acc + x })\n// 15\n\n// Enumerate\ng.SliceOf(\"a\", \"b\", \"c\").Iter().Enumerate().ForEach(func(i g.Int, v string) {\n    fmt.Printf(\"%d: %s\\n\", i, v)\n})\n\n// Using f package predicates\nimport \"github.com/enetx/g/f\"\n\ng.SliceOf(1, 2, 3, 4, 5).Iter().Filter(f.Ne(3)).Collect()       // [1, 2, 4, 5]\ng.SliceOf(\"\", \"a\", \"\").Iter().Exclude(f.IsZero).Collect()       // [\"a\"]\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eAll Iterator Methods\u003c/b\u003e\u003c/summary\u003e\n\n| Transform | Slice | Combine | Aggregate | Search | Other |\n|-----------|-------|---------|-----------|--------|-------|\n| `Map` | `Take` | `Chain` | `Collect` | `Find` | `ForEach` |\n| `Filter` | `Skip` | `Zip` | `Fold` | `Any` | `Inspect` |\n| `Exclude` | `StepBy` | `Enumerate` | `Reduce` | `All` | `Range` |\n| `FilterMap` | `First` | `Intersperse` | `Count` | `MaxBy` | `Scan` |\n| `FlatMap` | `Last` | `Cycle` | `Counter` | `MinBy` | `Combinations` |\n| `Flatten` | `Nth` | | `Partition` | | `Permutations` |\n| `Dedup` | `Chunks` | | `GroupBy` | | `Context` |\n| `Unique` | `Windows` | | | | `Chan` |\n| `SortBy` | | | | | `Parallel` |\n\n\u003c/details\u003e\n\n---\n\n## Mutex\n\nTyped mutex — data bound to lock.\n\n```go\ncounter := g.NewMutex(0)\n\n// Lock and modify\nguard := counter.Lock()\nguard.Set(guard.Get() + 1)\nguard.Unlock()\n\n// With defer (recommended)\nfunc increment(c *g.Mutex[int]) {\n    guard := c.Lock()\n    defer guard.Unlock()\n    guard.Set(guard.Get() + 1)\n}\n\n// Direct pointer access\nguard := counter.Lock()\ndefer guard.Unlock()\n*guard.Deref() += 1\n\n// Non-blocking\nif opt := counter.TryLock(); opt.IsSome() {\n    guard := opt.Unwrap()\n    defer guard.Unlock()\n    // got the lock\n}\n```\n\n**Why typed mutex?**\n```go\n// Traditional — easy to forget locking\ntype Old struct {\n    mu   sync.Mutex\n    data map[string]int  // what protects this?\n}\n\n// Typed — impossible to access without lock\ntype New struct {\n    data *g.Mutex[g.Map[string, int]]\n}\n\nfunc (s *New) Get(key string) g.Option[int] {\n    guard := s.data.Lock()\n    defer guard.Unlock()\n    return guard.Deref().Get(key)\n}\n```\n\n---\n\n## RwLock\n\nMultiple readers OR single writer.\n\n```go\nconfig := g.NewRwLock(Config{Port: 8080})\n\n// Read (concurrent)\nfunc getPort(c *g.RwLock[Config]) int {\n    guard := c.Read()\n    defer guard.Unlock()\n    return guard.Get().Port\n}\n\n// Write (exclusive)\nfunc setPort(c *g.RwLock[Config], port int) {\n    guard := c.Write()\n    defer guard.Unlock()\n    guard.Deref().Port = port\n}\n\n// Non-blocking\nif opt := config.TryRead(); opt.IsSome() { ... }\nif opt := config.TryWrite(); opt.IsSome() { ... }\n```\n\n| Use Case | Choose |\n|----------|--------|\n| Read-heavy (config, cache) | `RwLock` |\n| Write-heavy or balanced | `Mutex` |\n| Simple counters | `Mutex` |\n\n---\n\n## Pool\n\nGoroutine pool for parallel tasks.\n\n```go\nimport \"github.com/enetx/g/pool\"\n\np := pool.New[int]().Limit(4)\n\nfor i := range 10 {\n    p.Go(func() g.Result[int] {\n        return g.Ok(i * 2)\n    })\n}\n\nfor result := range p.Wait() {\n    if result.IsOk() {\n        fmt.Println(result.Unwrap())\n    }\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eWith Context and Cancel on Error\u003c/b\u003e\u003c/summary\u003e\n\n```go\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()\n\np := pool.New[int]().\n    Context(ctx).\n    CancelOnError().\n    Limit(4)\n\nfor i := range 100 {\n    p.Go(func() g.Result[int] {\n        if i == 50 {\n            return g.Err[int](errors.New(\"error\"))\n        }\n        return g.Ok(i)\n    })\n}\n\nfor result := range p.Wait() {\n    // stops after first error\n}\n```\n\n\u003c/details\u003e\n\n---\n\n## String\n\nExtended string with 80+ methods.\n\n```go\ns := g.String(\"Hello, World!\")\n\ns.Len()                         // 13\ns.Upper()                       // \"HELLO, WORLD!\"\ns.Lower()                       // \"hello, world!\"\ns.Contains(\"World\")             // true\ns.Split(\", \").Collect()         // [\"Hello\", \"World!\"]\ns.Trim()                        // remove whitespace\n\n// Conversions\ns.Std()                         // Go string\ns.Bytes()                       // Bytes type\ng.String(\"42\").TryInt()         // Result[Int]\n\n// Encoding\ns.Hash().MD5()                  // hash\ns.Encode().Base64()             // encode\ns.Compress().Gzip()             // compress\n```\n\n---\n\n## Int / Float\n\nNumeric types with utility methods.\n\n```go\ni := g.Int(42)\n\ni.Add(8)                        // 50\ni.Mul(2)                        // 84\ni.Abs()                         // absolute value\ni.Min(10, 20)                   // minimum\ni.Max(10, 20)                   // maximum\n\ni.IsZero()                      // false\ni.IsPositive()                  // true\ni.IsNegative()                  // false\n\ni.Binary()                      // binary string\ni.Hex()                         // hex string\n\n// Float\nf := g.Float(3.14159)\nf.Round()                       // Int(3)\nf.RoundDecimal(2)               // Float(3.14)\nf.Sqrt()                        // square root\n\n// Compare\ni.Cmp(g.Int(50))                // cmp.Less\n```\n\n---\n\n## Bytes\n\nExtended byte slice.\n\n```go\nb := g.Bytes([]byte(\"Hello\"))\n\nb.Len()\nb.Upper()\nb.Lower()\nb.Contains([]byte(\"ell\"))\n\nb.String()                      // to String\nb.Std()                         // to []byte\n```\n\n---\n\n## File / Directory\n\n### File\n\n```go\n// Read/Write\ncontent := g.NewFile(\"config.json\").Read()      // Result[String]\ng.NewFile(\"output.txt\").Write(\"Hello\")\ng.NewFile(\"log.txt\").Append(\"line\\n\")\n\n// Open a new file with the specified name \"text.txt\" and process it line by line.\ng.NewFile(\"text.txt\").\n\tLines().                            // Reads the file line by line.\n\tSkip(2).                            // Skips the first 2 lines in the iterator.\n\tExclude(f.IsZero).                  // Excludes lines that are empty or contain only whitespaces.\n\tDedup().                            // Removes consecutive duplicate lines.\n\tMap(g.String.Upper).                // Converts each line to uppercase.\n\tRange(func(s g.Result[g.String]) bool { // Iterates over the lines while a condition is true.\n\t\tif s.IsErr() { // Handles any errors encountered while reading lines.\n\t\t\tfmt.Println(\"Error:\", s.Err())\n\t\t\treturn false // Stops the iteration if an error occurs.\n\t\t}\n\n\t\tif s.Ok().Contains(\"COULD\") { // Checks if the line contains the substring \"COULD\".\n\t\t\treturn false // Stops the iteration if the condition is met.\n\t\t}\n\n\t\tfmt.Println(s.Ok()) // Prints the line.\n\t\treturn true         // Continues the iteration.\n\t})\n\n// Properties\nf := g.NewFile(\"test.txt\")\nf.Exist()                       // check existence\nf.Stat()                        // file info\nf.Copy(\"backup.txt\")            // copy\nf.Rename(\"new.txt\")             // rename\nf.Remove()                      // delete\n```\n\n### File Guard (Exclusive Lock)\n\n```go\nf := g.NewFile(\"data.txt\").Guard()  // holds exclusive lock\nf.Write(\"exclusive data\")\nf.Close()                           // release lock\n```\n\n### Directory\n\n```go\ng.NewDir(\"mydir\").Create()\ng.NewDir(\"path/to/deep\").CreateAll()\n\n// Read contents\nfor file := range g.NewDir(\".\").Read() {\n    if file.IsOk() {\n        file.Ok().Name().Println()\n    }\n}\n\n// Recursively walk through the directory tree starting from the current directory\ng.NewDir(\".\").Walk().\n\t// Exclude directories and symlinked directories\n\tExclude(func(f *g.File) bool { return f.IsDir() \u0026\u0026 f.Dir().Ok().IsLink() }).\n    // Exclude file symlinks\n\tExclude((*File).IsLink).\n\t// Process each walk result\n\tForEach(func(v g.Result[*g.File]) {\n\t\tif v.IsOk() {\n\t\t\t// Print the path of the file if no error occurred\n\t\t\tv.Ok().Path().Ok().Println()\n\t\t}\n\t})\n\n// Iterate over and print the names of files in the current directory with a *.go extension\ng.NewDir(\"*.go\").Glob().ForEach(func(f g.Result[*g.File]) { f.Ok().Name().Println() })\n\n// Copy the contents of the current directory to a new directory named \"copy\".\ng.NewDir(\".\").Copy(\"copy\").Unwrap()\n```\n\n---\n\n## Other Maps\n\n### MapOrd — Ordered Map\n\nMaintains insertion order.\n\n```go\nm := g.NewMapOrd[string, int]()\nm.Insert(\"c\", 3)\nm.Insert(\"a\", 1)\nm.Insert(\"b\", 2)\n\nfor k, v := range m.Iter() {\n    fmt.Println(k, v)  // c, a, b order\n}\n\nm.SortByKey(cmp.Cmp)            // sort by key\nm.SortByValue(cmp.Cmp)          // sort by value\n```\n\n### MapSafe — Concurrent Map\n\nThread-safe for concurrent access.\n\n```go\nm := g.NewMapSafe[string, int]()\n\n// Safe from multiple goroutines\ngo func() { m.Insert(\"a\", 1) }()\ngo func() { m.Get(\"a\") }()\n```\n\n---\n\n## License\n\nMIT License\n","funding_links":[],"categories":["Functional"],"sub_categories":["Search and Analytic Databases"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenetx%2Fg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenetx%2Fg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenetx%2Fg/lists"}