Skip to content
/ henry Public

Henry is a go library with generic helper functions in dealing with slices, maps and channels

License

Notifications You must be signed in to change notification settings

modfin/henry

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Henry

A collection of nice to have generic function and algorithms for slices, maps and channels

GoDoc Go report

This project came about in the experimentation with go1.18 and generics with helper functions for slices. It now also includes algorithms and constructs for dealing with channels and maps as well

It is expected to that there might be a lot of these types of libraries floating around after the release of go1.18. The go team did not include any of these fairly common constructs in this release but instead put some of them into the exp package. There for the might be quite a bit of overlap in the coming releases with this and other packages.

Some other work with similar concepts

Install

go get github.com/modfin/henry/...

Usage

Import the part of henry you are interested of using

import (
"github.com/modfin/henry/chanz"
"github.com/modfin/henry/mapz"
"github.com/modfin/henry/slicez"
)

Then use the functions in the libraries such as

upperPets := slicez.Map([]string{"Dog", "Lizard", "Cat"}, strings.ToUpper)) 
// []string{"DOG", "LIZARD", "CAT"}

Error handling

In go errors is made visible and is a core construct for sound code, so we can't simply ignore them. One way of dealing with them is to wrap the result in a result type. This does have some implication in that early returns might not be possible and might introduce some extra looping the check the result.

Example

package main

import (
	"fmt"
	"github.com/modfin/henry/exp/result"
	"github.com/modfin/henry/slicez"
	"net/url"
)

func parsUrls(stringUrls []string) ([]*url.URL, error) {
    urls := slicez.Map(stringUrls, func(u string) result.Result[*url.URL] {
        url, err := url.Parse(u)
        return result.From(url, err)
    })
    return result.Unwrap(urls)
}

func main() {
    stringUrls := []string{
        "https://example.com",
        "https://github.com",
        "bad\n url",
    }
    urls, err := parsUrls(stringUrls)
    fmt.Println("URLs", urls)
    // URLs [https://example.com https://github.com]
    
    fmt.Println("Error", err)
    // Error parse "bad\n url": net/url: invalid control character in URL
}

Content

Henry contain tree main packages. slicez, chanz and mapz

Functions in slicez

  • Clone
  • Compact
  • CompactFunc
  • Compare
  • CompareFunc
  • Complement
  • ComplementBy
  • Concat
  • Contains
  • ContainsFunc
  • Cut
  • CutFunc
  • Difference
  • DifferenceBy
  • Drop
  • DropRight
  • DropRightWhile
  • DropWhile
  • Each
  • Equal
  • EqualFunc
  • Every
  • EveryFunc
  • Filter
  • Find
  • FindLast
  • FlatMap
  • Flatten
  • Fold
  • FoldRight
  • GroupBy
  • Head
  • Index
  • IndexFunc
  • Intersection
  • IntersectionBy
  • Join
  • KeyBy
  • Last
  • LastIndex
  • LastIndexFunc
  • Map
  • Max
  • Min
  • None
  • NoneFunc
  • Nth
  • Partition
  • Reject
  • Reverse
  • Sample
  • Search
  • Shuffle
  • Some
  • SomeFunc
  • Sort
  • SortFunc
  • Tail
  • Take
  • TakeRight
  • TakeRightWhile
  • TakeWhile
  • Union
  • UnionBy
  • Uniq
  • UniqBy
  • Unzip
  • Unzip2
  • Zip
  • Zip2

Functions in mapz

  • Clear
  • Clone
  • Copy
  • DeleteFunc
  • DeleteValue
  • Equal
  • EqualFunc
  • Keys
  • Merge
  • Remap
  • Values

Functions in chanz

  • Collect
  • CollectUntil
  • Compact
  • Compact1
  • CompactN
  • CompactUntil
  • Concat
  • Concat1
  • ConcatN
  • ConcatUntil
  • Drop
  • Drop1
  • DropAll
  • DropN
  • DropUntil
  • DropWhile
  • DropWhile1
  • DropWhileN
  • DropWhileUntil
  • EveryDone
  • FanOut
  • FanOut1
  • FanOutN
  • FanOutUntil
  • Filter
  • Filter1
  • FilterN
  • FilterUntil
  • Flatten
  • Flatten1
  • FlattenN
  • FlattenUntil
  • Generate
  • Generate1
  • GenerateN
  • GenerateUntil
  • Map
  • Map1
  • MapN
  • MapUntil
  • Merge
  • Merge1
  • MergeN
  • MergeUntil
  • Partition
  • Partition1
  • PartitionN
  • PartitionUntil
  • Peek
  • Peek1
  • PeekN
  • PeekUntil
  • Readers
  • SomeDone
  • Take
  • Take1
  • TakeN
  • TakeUntil
  • TakeWhile
  • TakeWhile1
  • TakeWhileN
  • TakeWhileUntil
  • Unzip
  • Unzip1
  • UnzipN
  • UnzipUntil
  • Writers
  • Zip
  • Zip1
  • ZipN
  • ZipUntil

Slicez

The slicez package contains generic utility functions and algorithms for slices

Clone

Produces a copy of a given slice

s := []int{1,2,3}
clone := slicez.Clone[int](s)
// []int{1,2,3}

Compact

Removes consecutive duplicates from a slice

s := []int{1, 1, 2, 3, 3}
slicez.Compact[int](s)
// []int{1,2,3}

CompactFunc

Removes consecutive duplicates from a slice using a function for determine equality

s := []rune("Alot    of  white  spaces")
slicez.CompactFunc[rune](s, func(a, b rune) {
     return a == ' ' && a == b
})
// "Alot of white spaces"

Compare

Compares two slices for equality

s1 := []int{1, 2, 3}
s2 := []int{1, 2, 3}
slicez.Compare[int](s1, s2)
// 0

CompareFunc

Compares two slices for equality with supplied func

s1 := []int{1, 2, 3}
s2 := []int{4, 5, 6}
slicez.CompareFunc[int](s1, s2, func (a, b int) int{
return a%4 - b%4
})
// 0

Complement

Returns the complement of two slices

a := []int{1, 2, 3}
b := []int{3, 2, 5, 5, 6, 1}
slicez.Complement[int](a, b)
// []int{5, 6}

ComplementBy

Concat

Concatenates slices into a new slice

a := []int{1, 2, 3}
b := []int{4, 5, 6}
b := []int{7, 8, 9}
slicez.Concat[int](a, b, c)
// []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

Contains

Return true if an element is present in the slice

slicez.Contains[int]([]int{1, 2, 3, 4, 5}, 3)
// true

ContainsFunc

Returns true if the function returns true.

slicez.ContainsFunc[int]([]int{4, 5, 6, 7}, func(i int){ 
    return i % 4 == 3
})
// true

Cut

Cuts a slice into two parts

slicez.Cut[int]([]int{1,2,3,4,5}, 3)
// []int{1,2}, []int{4,5}, true

CutFunc

Cuts a slice into two parts

slicez.CutFunc[int]([]int{1,2,3,4,5}, func(i int){ return i == 3}) 
// []int{1,2}, []int{4,5}, true

Difference

Returns the difference between slices

a := []int{1,2,3}
b := []int{2,3,4}
c := []int{2,3,5}
slicez.Difference[int](a, b, c) 
// []int{1,4,5}

DifferenceBy

Drop

Drops the first N elements

slicez.Drop[int]([]int{1, 2, 3, 4, 5}, 2)
// []int{3,4,5}

DropRight

Drops the last N elements

slicez.DropRight[int]([]int{1, 2, 3, 4, 5}, 2)
// []int{1,2,3}

DropWhile

Drops elements from the left until function returns false

slicez.DropWhile[int]([]int{1, 2, 3, 4, 5}, func (i int) {return i < 3})
// []int{3,4,5}

DropRightWhile

Drops elements from the right until function returns false

slicez.DropRightWhile[int]([]int{1, 2, 3, 4, 5}, func (i int) {return i > 3})
// []int{1,2,3}

Each

Applies a function to each element of a slice

slicez.Each[int]([]int{1, 2, 3}, func (i int) { fmt.Print(i) })
// 123

Equal

Returns true if two slices are identical

s1 := []int{1, 2, 3}
s2 := []int{1, 2, 3}
slicez.Equal[int](s1, s2)
// true

EqualFunc

Returns true if two slices are identical, given an equality function

s1 := []int{1, 2, 3}
s2 := []int{4, 5, 6}
slicez.EqualFunc[int, int](s1, s2, func (a, b int) int{
return a%4 - b%4
})
// true

Every

Returns true if every element matches the given value

s1 := []int{1, 1, 1}
slicez.Every[int](s1, 1)
// true

EveryFunc

Every

Returns true if every element matches the given value using the equality function

s1 := []int{0, 3, 6}
slicez.EveryFunc[int](s1, func (i int) { return i % 3 == 0})
// true

Filter

Filters a slice to contain things we are looking for

s1 := []int{1, 2, 3, 4}
slicez.Filter[int](s1, func (i int) { return i % 2 == 0})
// []int{2,4}

Find

Find returns the first instance of an object where the function returns true

s1 := []int{1, 2, 3, 4, 5,6, 7}
slicez.Find[int](s1, func (i int) { return i % 3 == 0})
// 3

FindLast

FindLast returns the last instance of an object where the function returns true

s1 := []int{1, 2, 3, 4, 5,6, 7}
slicez.FindLast[int](s1, func (i int) { return i % 3 == 0})
// 6

FlatMap

Takes a slice, expands every element into a slice and flattens it to a single slice

s := []string{"a b c", "d e f"}

slicez.FlatMap(s, func(e string) []string {
    return strings.Split(e, " ")
})
// []string{"a","b","c","d","e","f"}

Flatten

Flattens a nested slice

s := [][]string{{"a", "b"}, {"c","d"}}
slicez.Flatten(s)
// []string{"a","b","c","d"}

Fold

Folds a slice into a value from the left (aka reduce)

s := []string{"a", "b", "c","d"}
slicez.Fold[string, string](s, func(acc string, str string) string { return acc + str}, ">")
// ">abcd"

FoldRight

Folds a slice into a value from the right (aka reduce)

s := []string{"a", "b", "c","d"}
slicez.FoldRight[string, string](s, func(acc string, str string) string { return acc + str}, ">")
// ">dcba"

GroupBy

Groups elements in a slice into a map

s = []int{0,1,2,3}
slicez.GroupBy(s, func(e int) int {return i % 2})
// map[int][]int{0: [0,2], 1:[1,2]}

Head

Returns the first element of a slice if present

slicez.Head([]int{1,2,3})
// 1, nil

Index

Returns the index of the first occurrence of an element

slicez.Index([]int{1,2,3}, 2)
// 1

IndexFunc

Returns the index of the first occurrence of an element using a function

slicez.IndexFunc([]int{1,2,3}, func(i int) bool {i % 2 == 1})
// 0

Intersection

Returns the intersection of slices

a := []int{1,2,3,4}
b := []int{3,4,5,6}
c := []int{3,4,8,9}
slicez.Intersection(a,b,c)
// []int{3,4}

IntersectionBy

Intersection

Returns the intersection of slices

a := []int{0,1}
b := []int{4,2}
c := []int{8,3}
slicez.IntersectionBy(func(i int) int {
    return i % 4
} a,b,c)
// []int{0,4,8}

Join

Joining a 2d slice into 1d slice using a glue

s = [][]string{{"hello", " ", "world"}, {"or", " ", "something"}}
slicez.Join(s, []string{" "})
// []string{"hello", " ", "world", " ", "or", s" ", "something"}

KeyBy

Returns a map with the slice elements in it, using the by function to determine key

s = []int{1,2,3,4}
slicez.KeyBy(s, func(i int) int { return i % 3 })
// map[int]int{0: 3, 1: 1, 2: 2}

Last

Returns the last element in a slice, or an error if len(s) == 0

slicez.Last([]int{1,2,3})
// 3, nil

LastIndex

Finds the last index of a needle, or -1 if not present

slicez.LastIndex([]int{1,1,2,1,3}, 1)
// 3

LastIndexFunc

LastIndex

Finds the last index of a func needle, or -1 if not present

slicez.LastIndex([]int{1,2,3,4,5}, func(i int) bool { return i % 3 == 1})
// 2

Map

Map values in a slice producing a new one

s := []int{1,2,3}
slicez.Map(s, func(i int) string { return fmt.Sprint(i)})
// []string{"1","2","3"}

Max

Returns the maximum value of a slice

s := []int{1,2,5,4}
slicez.Max(s...)
// 5

Min

Returns the minimum value of a slice

s := []int{1,2,5,0, 4}
slicez.Min(s...)
// 0

None

Returns true if no element match the needle

s := []int{1,2,3}
slicez.None(s, 0)
// true

NoneFunc

Returns true if no element returns true from the function

s := []int{1,2,3}
slicez.NoneFunc(s, func(i int) bool { return i < 1 })
// true

Nth

Returns the N:th element in a slice, zero value if empty and regards the slice as a modulo group

s := []int{1,2,3}
slicez.Nth(s, 1)
// 2
slicez.Nth(s, 3)
// 1
slicez.Nth(s, -1)
// 3

Partition

Returns two slices which represents the partitions

s := []int{1,2,3,4}
slicez.Partition(s, func(i int) bool { return i % 2 == 0})
// []int{2,4}, []int{1,3}

Reject

Reject is the complement to Filter and excludes items

s := []int{1,2,3,4}
slicez.Reject(s, func(i int) bool { return i % 2 == 0})
// []int{1,3}

Reverse

Reverses a slice

s := []int{1,2,3}
slicez.Reverse(s)
//[]int{3,2,1}

Sample

Returns a random sample of size N from the slice

s := []int{1,2,3,4,5,6,7,8}
slicez.Sample(s, 2)
//[]int{8,3}

Search

Shuffle

Returns a shuffled version of the slice

s := []int{1,2,3,4,5}
slicez.Shuffle(s)
//[]int{3,1,4,5,3}

Some

Returns true there exist an element in the slice that is equal to the needle, an alias for Contains

s := []int{1,2,3,4,5}
slicez.Some(s, 4)
//true

SomeFunc

Returns true if there is an element in the slice for which the predicate function returns true

s := []int{1,2,3,4,5}
slicez.SomeFunc(s, func(i int) bool { return i > 4})
//true

Sort

Sorts a slice

s := []int{3,2,1}
slicez.Sort(s)
//[]int{1,2,3}

SortFunc

Sorts a slice with a comparator

s := []int{1,2,3}
slicez.SortFunc(s, func(a, b int) bool { return b < a })
//[]int{3,2,1}

Tail

Returns the tail of a slice

s := []int{1,2,3}
slicez.Tail(s)
// []int{2,3}

Take

Returns the N first element of a slice

s := []int{1,2,3,4}
slicez.Take(s, 2)
// []int{1,2}

TakeRight

Returns the N last element of a slice

s := []int{1,2,3,4}
slicez.TakeRight(s, 2)
// []int{3, 4}

TakeWhile

Returns the first element of a slice that as long as function returns t

s := []int{1,2,3,4}
slicez.TakeRight(s, func(i int) bool { return i < 3})
// []int{1, 2}

TakeRightWhile

Returns the last element of a slice that as long as function returns t

s := []int{1,2,3,4}
slicez.TakeWhileRight(s, func(i int) bool { return i > 2})
// []int{3, 4}

Union

Returs the union of a slices

a := []int{1,2,3}
b := []int{3,4,5}
slicez.Union(a, b)
// []int{1,2,3,4,5}

UnionBy

Returs the union of a slices using a function for equality

a := []int{1,5}
b := []int{2,4}
slicez.UnionBy(func(i int) bool { return i % 2 == 0 } a, b)
// []int{1,2}

Uniq

Returns a slice of uniq elements

a := []int{1,2,3,1,3,4}
slicez.Uniq(a)
// []int{1,2,3,4}

UniqBy

Returns a slice of uniq elements, where equality is determined through the function

a := []int{1,2,3,1,3,4}
slicez.UniqBy(a, func(i int) bool { return i % 2 == 0 })
// []int{1,2}

Unzip

Takes a slice and unzips it into two slices

s := []int{-1,2}
slicez.Unzip(s, func(i int) (bool, int){
    return i > 0, int(Math.Abs(i))
})
// []bool{false, true}, []int{1,2}

Unzip2

Takes a slice and unzips it into three slices

s := []int{-2,-1,2}
slicez.Unzip(s, func(i int) (bool, bool, int){
    return i > 0, i % 2 == 0, int(Math.Abs(i))
})
// []bool{false, false, true}, []bool{true, false, true}, []int{2, 1,2}

Zip

Takes 2 slices and zips them into one slice

a := []int{1,2,3}
b := []string{"a","b","c"}
slicez.Zip(a,b, func(i int, s string) string {
    return fmt.Sprint(i, s)
})
// []string{"1a", "2b", "3c"}

Zip2

Takes 3 slices and zips them into one slice

a := []int{1,2,3}
b := []string{"a","b","c"}
b := []bool{true, false, true}
slicez.Zip(a, b, c, func(i int, s string, b bool) string {
    return fmt.Sprint(b, i, s)
})
// []string{"true1a", "false2b", "true3c"}

Mapz

The mapz package contains generic utility functions and algorithms for maps

Clear

Deletes every entry in a map

m := map[int]int{1:1, 2:2}
mapz.Clear(m)
// map[int]int{}

Clone

Creates a clone of a map

m := map[int]int{1:1, 2:2}
mapz.Clone(m)
// map[int]int{1:1, 2:2}

Copy

Copies one map into another

src := map[int]int{1:1, 2:2}
dst := map[int]int{1:0, 3:3}
mapz.Copy(dst, src)
//  map[int]int{1:1, 2:2, 3:3}

DeleteFunc

Will remove all entries from a map where the del function returns true

m := map[int]int{1:1, 2:2, 3:3}
mapz.DeleteFunc(m, func(k, v int) bool { return k == 2 })
//  map[int]int{1:1, 3:3}

DeleteValue

Deletes a value and the associated key from a map

m := map[int]int{1:1, 2:800, 3:3}
mapz.DeleteValue(m, 800)
//  map[int]int{1:1, 3:3}

Equal

Returns true if a map i equal

m1 := map[int]int{1:1, 3:3}
m2 := map[int]int{1:1, 3:3}
mapz.Equal(m1, m2)
// true

EqualFunc

Returns true if a map i equal using the equality function to test it

m1 := map[int]int{1:1, 3:3}
m2 := map[int]int{1:1, 3:6}
mapz.EqualFunc(m1, m2, func(a, b int) bool {return a % 3 == b % 3})
// true

Keys

Returns a slice of all keys in the map

m := map[int]int{1:1, 3:3}
mapz.Keys(m)
// []int{1,3}

Merge

Merges multiple maps into one map

m1 := map[int]int{1:1, 3:3, 4:800}
m2 := map[int]int{2:2, 4:4}
mapz.Merge(m1, m2)
// map[int]int{1:1, 2:2, 3:3, 4:4}

Remap

Remaps a map in terms of its keys and values

m := map[int]int{2:2, 4:4}
mapz.Remap(m, func(k, v int) (k2, v2 string){
    return fmt.Sprint(k), fmt.Sprint(v*2)
})
// map[string]string{"2":"4", "4":"8"}

Values

Returns a slice of all values in the map

m := map[int]int{2:6, 4:12}
mapz.Values(m)
// []int{6,12}

Chanz

The chanz package contains generic utility functions and algorithms for channels

SomeDone

Takes N channels as input and returns one channel. If any of the input channels is closed, the output channel is closed. This is used for control structure.

done1 := make(chan, interface{})
done2 := make(chan, interface{})

done := chanz.SomeDone(done1, done2)

go func(){
   time.Sleep(time.Second)
    close(done1)
    time.Sleep(time.Second)
    close(done2)
}

<- done // will read in 1 secound

EveryDone

Takes N channels as input and returns one channel. When all input channels is closed, the output channel will be closed. This is used for control structure.

done1 := make(chan, interface{})
done2 := make(chan, interface{})

done := chanz.SomeDone(done1, done2)

go func(){
    time.Sleep(time.Second)
    close(done1)
    time.Sleep(time.Second)
    close(done2)
}

<- done // will read in 2 seconds

Collect, CollectUntil

Will collect all read items into a slice and return it

in := chanz.Generate(1,2,3,4,5)
chanz.Collect(in)
// []int{1,2,3,4,5}

Compact, Compact1, CompactN, CompactUntil

Will remove consecutive duplicates from the channel

in := chanz.Generate(1,1,3,2,2,5,1)
w := chanz.Compact(in)
chanz.Collect(w)
// []int{1,3,2,5,1}

Concat, Concat1, ConcatN, ConcatUntil

Will concatenate channels

in1 := chanz.Generate(1,2,3)
in2 := chanz.Generate(4,5,6)
w := chanz.Concat(in1, in2)
chanz.Collect(w)
// []int{1,2,3,4,5,6}

Drop, Drop1, DropN, DropUntil

Drops the first N entries of the channel

in := chanz.Generate(1,2,3,4,5,6)
w := chanz.Drop(in, 2)
chanz.Collect(w)
// []int{3, 4, 5, 6}

DropWhile, DropWhile1, DropWhileN, DropWhileUntil

Drops the first entries of the channel until function returns true

in := chanz.Generate(1,2,3,4,5,6,1)
w := chanz.DropWhile(in, func(i int) bool { return i < 3})
chanz.Collect(w)
// []int{3, 4, 5, 6, 1}

DropAll

Drops all elements until closed

in := chanz.Generate(1,2,3,4,5,6)
w := chanz.DropAll(in, false)
chanz.Collect(w)
// []int{}

DropBuffer

Drops all elements that is buffered in the chan

in :=  chanz.GenerateWith[int](chanz.Buffer(2))(1,2,3,4,5,6)
chanz.DropBuffer(in, false)
chanz.Collect(in)
// []int{3,4,5,6}

TakeBuffer

Take all elements that is buffered in the chan

in := chanz.GenerateWith[int](chanz.Buffer(2))(1,2,3,4,5,6)
r := chanz.TakeBuffer(in)
// []int{1,2}
c := chanz.Collect(w)
// []int{3,4,5,6}

FanOut

Takes an input channel and fans it out to multiple output channels

in := chanz.Generate(1,2,3,4,5,6)
chans := chanz.FanOut(in, 2)
go chanz.Collect(chans[0])
chanz.Collect(chans[1])
// []int{1,2,3,4,5,6}
// []int{1,2,3,4,5,6}

Filter

Filters the items read onto the output chan

in := chanz.Generate(1,2,3,4,5,6)
even := chanz.Filter(in, func(i int) bool { return i % 2 == 0})
chanz.Collect(even)
// []int{2,4,6}

Flatten

Flattens a channel that produces slices

in := chanz.Generate([]int{1,2,3}, []int{4,5,6})
w := chanz.Flatten(in)
chanz.Collect(w)
// []int{1,2,3,4,5,6}

Generate

Takes elements, creates a channel and writes the elements to it

w := chanz.Generate(1,2,3,4)
chanz.Collect(w)
// []int{1,2,3,4}

Map

Maps element from one channel to another

in := chanz.Generate(1,2,3,4)
w := chanz.Map(in, func(i int) string { return fmt.Sprint(i) })
chanz.Collect(w)
// []string{"1","2","3","4"}

Merge

Merge will take N chans and merge them onto one channel (in a non-particular order)

in1 := chanz.Generate(1,2,3)
in2 := chanz.Generate(4,5,6)
w := chanz.Merge(in1, in2)
chanz.Collect(w)
// []int{4,1,5,6,2,3}

Partition

Partition a channel into to two channels

in := chanz.Generate(1,2,3,4,5,6)
even, odd := chanz.Partition(in, func(i int) bool { return i % 2 == 0})
go chanz.Collect(even)
chanz.Collect(odd)
// []int{2,4,6}
// []int{1,3,5}

Peek

Will produce a channel that runs a function for each item

in := chanz.Generate(1,2,3,4,5,6)
in := chanz.Peek(in, func(i int){ fmt.Print(i)})
chanz.Collect(in)
// 123456
// []int{1,2,3,4,5,6}

Take

Will take the first N items from the channel

in := chanz.Generate(1,2,3,4,5,6)
w := chanz.Take(in, 2)
chanz.Collect(w)
// []int{1,2}

TakeWhile

Will take the first items from the channel until the predicate function returns false

in := chanz.Generate(1,2,3,4,5,6)
w := chanz.TakeWhile(in, func(i int) bool{ return i < 3})
chanz.Collect(w)
// []int{1,2}

Unzip

Takes one chan and unzips it into two

in := chanz.Generate(-2, -1, 1, 2)
possitive, value := chanz.Unzip(in, func(i int) (bool, int) {
    return i > 0, Math.Abs(i)
})
go chanz.Collect(possitive)
chanz.Collect(value)
// []bool{false, false, true, true}
// []int{2,1,1,2}

Zip

Takes two channels and zips them into one channel

in1 := chanz.Generate(1,2,3)
in2 := chanz.Generate("a","b","c")
x := chanz.Unzip(in1, in2, func(i int, s string) string {
    return fmt.Sprint(i,s)
})
chanz.Collect(w)
// []string{"1a", "2b", "3c"}

Readers

Takes a slice of channels and returns a slice casted to read channels

Writers

Takes a slice of channels and returns a slice casted to write channels

About

Henry is a go library with generic helper functions in dealing with slices, maps and channels

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages