常用Golang工具类函数实现(二)

2023-08-10 18:18:21 浏览数 (1)

概要

在使用Golang开发中,标准库提供了很多好用的函数可以帮助我们快速的实现一些功能。但是相对于其他语言来说,还是有很多好用且常用的函数或者方法,是没有被加入到标准库的,这里就需要我们自己的来实现。

好用的函数

9. ArrayMerge 将任意多个切片合并成一个切片

源码

代码语言:go复制
func ArrayMerge[T any](ss ...[]T) []T {
    var result []T
    for _, s := range ss {
        result = append(result, s...)
    }
    return result
}

测试

代码语言:go复制
func TestArrayMerge(t *testing.T) {
    arr1 := []string{"A", "B", "C"}
    arr2 := []string{"D", "E", "F"}
    arr3 := []int{1, 2, 3}
    arr4 := []int{4, 5, 6}
    fmt.Println(ArrayMerge(arr1, arr2))
    fmt.Println(ArrayMerge(arr3, arr4))
}

结果

代码语言:txt复制
=== RUN   TestArrayMerge
[A B C D E F]
[1 2 3 4 5 6]
--- PASS: TestArrayMerge (0.00s)
PASS

10. ArrayChunk 将一个切片分割成多个切片

源码

代码语言:go复制
func ArrayChunk[T any](s []T, size int) [][]T {
    if size <= 0 {
        return nil
    }

    var chunks [][]T
    for i := 0; i < len(s); i  = size {
        end := i   size
        if end > len(s) {
            end = len(s)
        }
        chunks = append(chunks, s[i:end])
    }
    return chunks
}

测试

代码语言:go复制
func TestArrayChunk(t *testing.T) {
    a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    chunks := ArrayChunk(a, 3)
    fmt.Println(chunks) // 输出 [[1 2 3] [4 5 6] [7 8 9]]

    b := []string{"Hello", "world", "你好", "世界"}
    chunks2 := ArrayChunk(b, 2)
    fmt.Println(chunks2) // 输出 [[Hello world] [你好 世界]]
}

结果

代码语言:txt复制
=== RUN   TestArrayChunk
[[1 2 3] [4 5 6] [7 8 9]]
[[Hello world] [你好 世界]]
--- PASS: TestArrayChunk (0.00s)
PASS

11. ArrayPad 将切片填充元素,并使总元素数达到固定个数

源码

代码语言:go复制
func ArrayPad[T any](s []T, size int, val T) []T {
    if size > 0 {
        for i := len(s); i < size; i   {
            s = append(s, val)
        }
    } else if size < 0 {
        for i := len(s); i < -size; i   {
            s = append([]T{val}, s...)
        }
    }
    return s
}

说明

size: 表示填充完成后,最终的切片元素数量

测试

代码语言:go复制
func TestArrayPad(t *testing.T) {
    a := []int{1, 2, 3}
    padded := ArrayPad(a, 5, 0)
    fmt.Println(padded) // 输出 [1 2 3 0 0]

    b := []string{"Hello", "world"}
    padded2 := ArrayPad(b, -4, "你好")
    fmt.Println(padded2) // 输出 [你好 你好 Hello world]
}

结果

代码语言:txt复制
=== RUN   TestArrayPad
[1 2 3 0 0]
[你好 你好 Hello world]
--- PASS: TestArrayPad (0.00s)
PASS

12. ArrayRand 随机从原来切片中取N个元素,生成新的切片

源码

代码语言:go复制
func ArrayRand[T any](s []T, n int) []T {
    if n <= 0 || n > len(s) {
        return nil
    }
    // 1.20之后,不需要这行
    rand.Seed(time.Now().UnixNano())
    rand.Shuffle(len(s), func(i, j int) { s[i], s[j] = s[j], s[i] })

    return s[:n]
}

测试

代码语言:go复制
func TestArrayRand(t *testing.T) {
    a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    random := ArrayRand(a, 3)
    fmt.Println(random) // 输出的结果会随机,例如 [7 2 1]

    b := []string{"Hello", "world", "你好", "世界"}
    random2 := ArrayRand(b, 2)
    fmt.Println(random2) // 输出的结果会随机,例如 [你好 world]
}

结果

代码语言:txt复制
=== RUN   TestArrayRand
[7 2 1]
[Hello 世界]
--- PASS: TestArrayRand (0.00s)
PASS

13. ArrayColumn 从元素为map的切片中,找到所有map指定的key对应的value值,并返回切片

源码

代码语言:go复制
func ArrayColumn[T any, K comparable](maps []map[K]T, key K) []T {
    var column []T
    for _, m := range maps {
        if val, ok := m[key]; ok {
            column = append(column, val)
        }
    }
    return column
}

测试

代码语言:go复制
func TestArrayColumn(t *testing.T) {
    maps := []map[string]interface{}{
        {"name": "Alice", "age": 20},
        {"name": "Bob", "age": 25},
        {"name": "Charlie", "age": 30},
    }

    names := ArrayColumn(maps, "name")
    fmt.Println(names) // 输出 [Alice Bob Charlie]

    ages := ArrayColumn(maps, "age")
    fmt.Println(ages) // 输出 [20 25 30]
}

结果

代码语言:txt复制
=== RUN   TestArrayColumn
[Alice Bob Charlie]
[20 25 30]
--- PASS: TestArrayColumn (0.00s)
PASS

14. IsNumeric 判断一个元素是否为数值类型

源码

代码语言:go复制
func IsNumeric(s any) bool {
    switch v := s.(type) {
    case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64:
        return true
    case string:
        _, err := strconv.ParseFloat(v, 64)
        return err == nil
    default:
        return false
    }
}

测试

代码语言:go复制
func TestIsNumeric(t *testing.T) {
    fmt.Println(IsNumeric("123"))          // 输出 true
    fmt.Println(IsNumeric("123.456"))      // 输出 true
    fmt.Println(IsNumeric(3.14))           // 输出 true
    fmt.Println(IsNumeric("abc"))          // 输出 false
    fmt.Println(IsNumeric([]int{1, 2, 3})) // 输出 false
}

结果

代码语言:txt复制
=== RUN   TestIsNumeric
true
true
true
false
false
--- PASS: TestIsNumeric (0.00s)
PASS

15. IsIP 判断一个字符串是否是IP地址

源码

代码语言:go复制
func IsIP(ip string) bool {
    return net.ParseIP(ip) != nil
}

测试

代码语言:go复制
func TestIsIP(t *testing.T) {
    fmt.Println(IsIP("192.168.1.1"))                             // 输出 true
    fmt.Println(IsIP("2001:0db8:85a3:0000:0000:8a2e:0370:7334")) // 输出 true
    fmt.Println(IsIP("not an ip address"))                       // 输出 false
}

结果

代码语言:txt复制
=== RUN   TestIsIP
true
true
false
--- PASS: TestIsIP (0.00s)
PASS

16. RandomBytes 随机生成指定长度的字节数组

源码

代码语言:go复制
func RandomBytes(len int) ([]byte, error) {
    b := make([]byte, len)
    _, err := rand.Read(b)
    // 注意这里返回的n是读取的字节数
    if err != nil {
        return nil, err
    }
    return b, nil
}

测试

代码语言:go复制
func TestRandomBytes(t *testing.T) {
    fmt.Println(RandomBytes(10))
    fmt.Println(RandomBytes(10))
    fmt.Println(RandomBytes(10))
}

结果

代码语言:txt复制
=== RUN   TestRandomBytes
[214 128 69 198 193 234 254 166 29 110] <nil>
[63 173 191 149 30 203 152 31 158 225] <nil>
[182 52 129 169 133 60 237 248 255 234] <nil>
--- PASS: TestRandomBytes (0.00s)
PASS
go

0 人点赞