Kyle Banks

Benefits of Creating Your Own go-kit

Written by @kylewbanks on Jul 4, 2016.

Like most languages, Go values small, reusable, self contained packages and functions that can be easily reused, tested, and modified. In order to accommodate this, I find the best thing to do is to create your own go-kit, a collection of small packages that each have a very specific purpose.

Here's a look at my go-kit on GitHub:

Each folder represents a separate package, most of which have no dependencies on each-other, or any other packages for that matter. This means that they are easy to test, easy to reuse, and easy to maintain.

Using govendor, I can easily add specific packages to a new project as needed:

govendor fetch github.com/KyleBanks/go-kit/cache

Or grab all of them for bigger projects that need it:

govendor fetch github.com/KyleBanks/go-kit/...

Even when developing a closed source project, this allows you to open up the bits that are not specifically related to your project, and gain all the benefits of open source projects and reusable modules.

Because most packages are so small, ensuring their quality is very straightforward. For example, let's look at the contains package. The purpose of this package is to provide the ability to see if a slice contains a particular value. At the time of writing, I only needed this functionality for integer slices, so that's all it supports. As I need this functionality for other data-types, it will be easy to add to the package, write unit tests, and update my project by govendor-ing my go-kit.

package contains

// Int returns true if the slice of ints contains the value provided.
func Int(val int, arr []int) bool {
	for _, i := range arr {
		if i == val {
			return true
		}
	}

	return false
}

And now for some test cases:

package contains

import "testing"

func TestInt(t *testing.T) {
	// Negative cases
	if Int(0, []int{}) {
		t.Fatal("Expected value not to be in empty slice")
	} else if Int(0, []int{1, 2, 3}) {
		t.Fatal("Expected value not to be in slice")
	}

	// Positive Cases
	if !Int(0, []int{1, 2, 3, 0}) {
		t.Fatal("Expected value to be in slice")
	}
}

And now I can be confident that I can drop this tiny package into any project and know it will work, without having to write anything other than:

import "github.com/KyleBanks/go-kit/contains"

...
ints := []int {...}
val := 1

if contains.Int(val, ints) {
    ...
}
Let me know if this post was helpful on Twitter @kylewbanks or down below!