Enjoy a slice! pie
is a code generator for dealing with slices that
focuses on type safety, performance and immutability.
Install/update:
go get -u github.com/elliotchance/pie
pie
ships with some slice types ready to go (pun intended). These include:
These can be used without needing go generate
. For example:
package main
import (
"github.com/elliotchance/pie/pie"
"fmt"
)
func main() {
name := pie.Strings{"Bob", "Sally", "John", "Jane"}.
Unselect(func (name string) {
return strings.HasPrefix(name, "J")
}).
Transform(strings.ToUpper).
Last()
fmt.Println(name) // "SALLY"
}
Annotate the slice type in your source code:
type Car struct {
Name, Color string
}
//go:generate pie Cars
type Cars []Car
Run go generate
. This will create a file called cars_pie.go
. You should
commit this with the rest of your code. Run go generate
any time you need to
add more types.
Now you can use the slices:
cars := Cars{
{"Bob", "blue"},
{"Sally", "green"},
{"John", "red"},
{"Jane", "red"},
}
redCars := cars.Select(func(car Car) bool {
return car.Color == "red"
})
// redCars = Cars{{"John", "red"}, {"Jane", "red"}}
Or, more complex operations can be chained:
cars.Unselect(func (car Car) {
return strings.HasPrefix(car.Name, "J")
}).
Transform(func (car Car) Car {
car.Name = strings.ToUpper(car.Name)
return car
}).
Last()
// Car{"SALLY", "green"}
By default all functions will be generated. This is easy to get going but creates a lot of unused code. You can limit the functions generated by chaining the function names with a dot syntax, like:
//go:generate myInts.Average.Sum myStrings.Select
This will only generate myInts.Average
, myInts.Sum
and myStrings.Select
.
Function | String | Number | Struct | Big-O | Description |
---|---|---|---|---|---|
Append |
β | β | β | n | A new slice with the elements appended to the end. |
AreSorted |
β | β | n | Check if the slice is already sorted. | |
AreUnique |
β | β | n | Check if the slice contains only unique elements. | |
Average |
β | n | The average (mean) value, or a zeroed value. | ||
Contains |
β | β | β | n | Check if the value exists in the slice. |
Extend |
β | β | β | n | A new slice with the elements from each slice appended to the end. |
First |
β | β | β | 1 | The first element, or a zeroed value. |
FirstOr |
β | β | β | 1 | The first element, or a default value. |
Join |
β | n | A string from joining each of the elements. | ||
JSONString |
β | β | β | n | The JSON encoded string. |
Last |
β | β | β | 1 | The last element, or a zeroed value. |
LastOr |
β | β | β | 1 | The last element, or a default value. |
Len |
β | β | β | 1 | Number of elements. |
Max |
β | β | n | The maximum value, or a zeroes value. | |
Min |
β | β | n | The minimum value, or a zeroed value. | |
Reverse |
β | β | β | n | Reverse elements. |
Select |
β | β | β | n | A new slice containing only the elements that returned true from the condition. |
Sort |
β | β | nβ log(n) | Return a new sorted slice. | |
Sum |
β | n | Sum (total) of all elements. | ||
ToStrings |
β | β | β | n | Transforms each element to a string. |
Transform |
β | β | β | n | A new slice where each element has been transformed. |
Unique |
β | β | nβ log(n) | Return a new slice with only unique elements. | |
Unselect |
β | β | β | n | A new slice containing only the elements that returned false from the condition. |
pie
supports many Go versions, all the way back to Go 1.8.
-
Type safety. I never want to hit runtime bugs because I could pass in the wrong type, or perform an invalid type case out the other end.
-
Performance. The functions need to be as fast as native Go implementations otherwise there's no point in this library existing.
-
Nil-safe. All of the functions will happily accept nil and treat them as empty slices. Apart from less possible panics, it makes it easier to chain.
-
Immutable. Functions never modify inputs, unlike some built-ins such as
sort.Strings
.
Absolutely. Pull requests are always welcome. Your PR must include:
- Unit tests.
- Update the README to list the new functions.
I wanted to pick a name for the project that was short and had an associated emoji. I liked pie, but then I found out that the pie emoji is not fully supported everywhere. I didn't want to change the name of the project to cake, but pizza pie still made sense. I'm not sure if I will change it back to a pie later.