package main
import (
"fmt"
"sort"
"golang.org/x/exp/constraints"
)
// Keys retrieves the keys from the map m as a slice.
// The order of the keys is unpredictable.
// This function includes two type parameters: K and V.
// Map keys must be comparable, meaning K must satisfy the
// predeclared constraint of being comparable. Values in the
// map can be of any type.
func Keys[K comparable, V any](m map[K]V) []K {
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
// Filter removes values from a slice based on a filter function.
// It returns a new slice containing only the elements of s
// for which the function f returns true.
func Filter[T any](s []T, f func(T) bool) []T {
var r []T
for _, v := range s {
if f(v) {
r = append(r, v)
}
}
return r
}
// Sort sorts a slice of any orderable type T.
// The constraints.Ordered constraint in the Sort() function ensures
// that it can sort values of any type that supports the operators <, <=, >=, and >.
func Sort[T constraints.Ordered](s []T) {
sort.Slice(s, func(i, j int) bool {
return s[i] < s[j]
})
}
// Define type Number with constraints
type Number interface {
constraints.Float | constraints.Integer
}
// Multiply number by 2
func Double[T Number](value T) T {
return value * 2
}
// Sum calculates the total of the values in a map that contains numeric or float values.
func Sum[K comparable, V Number](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}
// Scale returns a copy of s with each element multiplied by c.
func Scale[S ~[]E, E constraints.Integer](s S, c E) S {
r := make(S, len(s))
for i, v := range s {
r[i] = v * c
}
return r
}
func main() {
k := Keys(map[int]int{1: 2, 2: 4})
fmt.Println(k)
sum := Sum(map[int]int{1: 2, 2: 4})
fmt.Println(sum)
s := []int{1, 2, 3, 7, 5, 22, 18}
evens := Filter(s, func(i int) bool { return i%2 == 0 })
fmt.Println(evens)
Sort(s)
fmt.Println(s)
fmt.Println(Double(23))
fmt.Println(Double(23.23))
intValues := map[string]int64{
"first": 23,
"second": 565,
"third": 755,
}
fmt.Println(Sum(intValues))
sc := Scale([]int{1, 2, 3}, 2)
fmt.Println(sc)
}
Generics is a feature that enables you to write reusable and type-safe code. With generics, you can create functions and data structures that operate on multiple types without requiring runtime type assertions or type casting. Here are examples of using generics in Go.