xpsuper / gtl

Golang Template Library (GTL). Common data structures using Golang generics.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

GTL: Golang Template Library

GTL is a template library written in pure Go(2). It is intended to hold common data structures that might be missing in the standard library or they are cumbersome if generics are not present (using interface{} as replacement, type casting, etc...).

You can learn more about Golang's generics here.

Table of Contents

  1. Result
  2. Optional
  3. Iterator
  4. Vector
  5. Bytes
  6. Locker
  7. Numeric

Result

Result tries to emulate Rust's result. But being honest, it is more similar to std::expected from C++.

As Golang already has a type for defining errors, the second type is replaced with the error.

After getting the returned value, we can manage the Result in different ways.

A valid usage would be:

func Do() (r gtl.Result[string]) {
  if rand.Intn(100) & 1 == 0 { // is even?
    return r.Err(
      errors.New("unexpected result"))
  }
  
  return r.Ok("Success")
}

func onSuccess(v string) {
	fmt.Printf("Got result: %s\n", v)
}

func onError(err error) {
	fmt.Printf("Got error: %s\n", err)
}

func main() {
  Do().Then(onSuccess).Else(onError)
}

Then is executed if Do returned the call to Ok. Ok will store the string "Success" into the Result's expected value. In the other hand, Else will be executed if Err has been called.

If we don't want to handle errors but we just want to get the value, we can do the following:

func Do() (r gtl.Result[string]) {
  // assume Do() didn't change
}

func main() {
  fmt.Printf("Got %s\n", Do().Or("Failed"))
}

Optional

Optional represents an optional value. In C++ we have the std::optional which might be similar.

A valid usage would be:

func myFunc() (o gtl.Optional[int]) {
	if n := rand.Int(); n % 2 == 0 { // is even
		o.Set(n)
	}
	
	return o
}

func main() {
	value := myFunc()
	if value.Has() {
		fmt.Printf("Got: %d\n", value.V())
	}
}

Iterator

Iterator tries to emulate a C++'s iterator. It is defined as follows:

// Iterator defines an interface for iterative objects.
type Iterator[T any] interface {
	// Next increments the iterator.
	Next() bool
	// Advance advances the cursor `n` steps. Returns false if `n` overflows.
	Advance(n int) bool
	// V returns the value held in the iterator.
	V() T
	// Ptr returns a pointer to T.
	Ptr() *T
}

Vector

Vec tries to emulate a C++'s vector (somehow). It doesn't try to emulate it exactly, but it just works as a C++ vector in a way that internally is just a slice with some helper functions, in this case functions like Append, Push, PopBack, PopFront or Len.

A valid usage would be:

package main

import (
        "os"
        "sort"
        "fmt"

        "github.com/dgrr/gtl"
)

func main() {
        vec := gtl.NewVec(os.Args[1:]...)

        sort.Slice(vec, func(i, j int) bool {
                return vec[i] < vec[j]
        })

        fmt.Println(vec)
}

Bytes

Bytes is a helper for working with byte slices.

You can see an example of how to use Bytes here.

Locker

A Locker defines a helper structure to facilitate Lock and Unlock wrappers.

func main() {
	lck := NewLocker[int]()
	lck.Set(20)
	
	fmt.Println(lck.V())
	
	lck.Lock()
	*lck.Ptr() += 20
	lck.Unlock()
	
	fmt.Println(lck.V())
}

Numeric

There are global numeric helper functions like Max and Min.

About

Golang Template Library (GTL). Common data structures using Golang generics.


Languages

Language:Go 100.0%