Golang generic, make our programming work easier, we only need to write less code, to achieve multi-functional functions.

Table of Contents

Introduction

We will use golang generics to write several common sorting algorithms such as bubble sort, insertion sort, etc. Then test if the sorting algorithm works properly.

Implementation

Define the Constraints

package constraints

// Signed is a generic type constraint for all signed integers
type Signed interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64
}

// Unsigned is a generic type constraint for all unsigned integers
type Unsigned interface {
	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}

// Integer is a generic type constraint for all integers(signed and unsigned)
type Integer interface {
	Signed | Unsigned
}

// Float is a generic type constraint for all floating point types
type Float interface {
	~float32 | ~float64
}

// Number is a generic type constraint for all numeric type in Go except Complex types
type Number interface {
	Integer | Float
}

// Ordered is a generic type constraint for all ordered data types in Go
type Ordered interface {
	Integer | ~string | Float
}

Sorting Algorithms

  • Bubble Sort
func BubbleSort[T constraints.Ordered](arr []T) []T {
	swapped := true

	for swapped {
		swapped = false
		// `length -i - 1` is for ignoring comparisons of elements which have
		// already been compared in earlier iterations
		for i := 0; i < len(arr)-1; i++ {
			if arr[i+1] < arr[i] {
				// here swapping of positions is being done
				arr[i+1], arr[i] = arr[i], arr[i+1]
				swapped = true
			}
		}
	}

	return arr
}
  • Insertion Sort
func InsertionSort[T constraints.Ordered](arr []T) []T {
	for currentIndex := 1; currentIndex < len(arr); currentIndex++ {
		// storing current element whose left side is checked for
		// its correct position
		temp := arr[currentIndex]
		iterator := currentIndex

		// check whether the adjacent element in left side is greater or
		// less than the current element
		for ; iterator > 0 && arr[iterator-1] >= temp; iterator-- {

			// moving the left side element to one position forward
			arr[iterator] = arr[iterator-1]
		}

		// moving current element to its  correct position
		arr[iterator] = temp
	}

	return arr
}

Testing

Generic BubbleSort

Integer

func main() {
	ints := []int{1, 4, 6, 2, 8, -1, -4, -2, 9}
	fmt.Println(sorts.BubbleSort(ints))
}

// Output:
//  [-4 -2 -1 1 2 4 6 8 9]

Floating

func main() {
	floats := []float64{2.1, 3.2, -3, 9, 7, 8.3}
	fmt.Println(sorts.BubbleSort(floats))
	Output:
}

// Output:
//  [-3 2.1 3.2 7 8.3 9]

Strings

func main() {
	strs := []string{"obama", "trump", "biden"}
	fmt.Println(sorts.BubbleSort(strs))
}

// Output:
//  [biden obama trump]

Generic InsertionSort

As we expected, it is consistent with the results of BubbleSort.

Conclusion

By using generics, some repetitive code is reduced and our work is made easier. Thanks for reading, the full code is in my GitHub repository awesome-golang-algorithm.

Reference