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

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

概要

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

好用的函数

1. Implode 将任意类型数组,按照分割符,转成字符串

源码

代码语言:go复制
func Implode[T any](arr []T, delimiter string) string {
    var result string
    for i, v := range arr {
        if i > 0 {
            result  = delimiter
        }
        result  = fmt.Sprintf("%v", v)
    }
    return result
}

测试

代码语言:go复制
func TestImplode(t *testing.T) {
    arr1 := []string{"A", "B", "C"}
    arr2 := []int{1, 2, 3}
    arr3 := []interface{}{1, "B", 3}
    fmt.Println(Implode(arr1, ","))
    fmt.Println(Implode(arr2, ","))
    fmt.Println(Implode(arr3, ","))
}

结果

代码语言:txt复制
=== RUN   TestImplode
A,B,C
1,2,3
1,B,3
--- PASS: TestImplode (0.00s)
PASS

2. InSlice 判断一个元素,是否包含在一个切片内

源码

代码语言:go复制
func InSlice[T comparable](need T, arr []T) bool {
    for _, v := range arr {
        if v == need {
            return true
        }
    }
    return false
}

测试

代码语言:go复制
func TestInSlice(t *testing.T) {
	arr1 := []string{"A", "B", "C"}
	arr2 := []int{1, 2, 3}
	arr3 := []interface{}{1, "B", 3}
	fmt.Println(InSlice("A", arr1))
	fmt.Println(InSlice(2, arr2))
	// []interface{} 类型的需要go1.20以上版本
	fmt.Println(InSlice(3, arr3))
}

结果

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

3. Empty 判断一个变量,是否为空值

源码

代码语言:go复制
// EmptyInterface 定义Empty接口
type EmptyInterface interface {
    IsEmpty() bool
}

type MyString string
type MyInt int
type MySlice []int

func (s MyString) IsEmpty() bool {
    return s == ""
}

func (i MyInt) IsEmpty() bool {
    return i == 0
}

func (sl MySlice) IsEmpty() bool {
    return len(sl) == 0
}

func Empty[T EmptyInterface](val T) bool {
    return val.IsEmpty()
}

说明

在这个示例中,我们首先定义了一个名为EmptyInterface的接口,该接口包含一个名为IsEmpty的方法。然后,我们为MyString、MyInt和MySlice类型定义了IsEmpty方法,使它们满足EmptyInterface接口。最后,我们定义了一个泛型函数Empty,该函数接受一个满足EmptyInterface接口的参数,并调用其IsEmpty方法来判断它是否为空。

这种方法的优点是避免了反射的使用,提高了性能。但是,它需要为每种需要检查是否为空的类型定义一个满足EmptyInterface接口的方法,这可能会增加代码的复杂性。

测试

代码语言:go复制
func TestEmpty(t *testing.T) {
    fmt.Println(Empty(MyString("")))      // true
    fmt.Println(Empty(MyString("hello"))) // false
    fmt.Println(Empty(MyInt(0)))          // true
    fmt.Println(Empty(MyInt(42)))         // false
    fmt.Println(Empty(MySlice{}))         // true
    fmt.Println(Empty(MySlice{1, 2}))     // false
}

结果

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

4. Strpos 判断一个字符串在另一个字符串的首次出现的位置

源码

代码语言:go复制
func Strpos(haystack, needle string, offset int) int {
    length := len(haystack)
    if length == 0 || offset > length || -offset > length {
        return -1
    }

    if offset < 0 {
        offset  = length
    }
    pos := strings.Index(haystack[offset:], needle)
    if pos == -1 {
        return -1
    }
    return pos   offset
}

说明

haystack为查找之所在的字符串,needle为要查找的字符串,offset为偏移量,当offset设置为0的时候,则从头开始查找。

测试

代码语言:go复制
func TestStrpos(t *testing.T) {
    str := "abcdsj1dhakadk"
    fmt.Println(Strpos(str, "d", 0))
    fmt.Println(Strpos(str, "1", 0))
    fmt.Println(Strpos(str, "a", 2))
}

结果

代码语言:txt复制
=== RUN   TestStrpos
3
6
9
--- PASS: TestStrpos (0.00s)
PASS

5. Ucfirst 将字符串首字母大写

源码

代码语言:go复制
func Ucfirst(s string) string {
    if len(s) == 0 {
        return s
    }
    firstRune := []rune(s)[0]
    if unicode.IsLower(firstRune) {
        firstRune = unicode.ToUpper(firstRune)
    }
    return string(firstRune)   s[1:]
}

测试

代码语言:go复制
func TestUcfirst(t *testing.T) {
    fmt.Println(Ucfirst("hello"))
    fmt.Println(Ucfirst("i am lisi"))
    fmt.Println(Ucfirst("34"))
}

结果

代码语言:txt复制
=== RUN   TestUcfirst
Hello
I am lisi
34
--- PASS: TestUcfirst (0.00s)
PASS

6. Substr 切割字符串

源码

代码语言:go复制
func Substr(str string, start uint, length int) string {
    runes := []rune(str)
    strLen := len(runes)

    if start >= uint(strLen) {
        return ""
    }

    if length < 0 || int(start) length > strLen {
        length = strLen - int(start)
    }

    return string(runes[start : start uint(length)])
}

说明

str为要切割的目标字符串,start为切割的起始位置,length为切割的长度

测试

代码语言:go复制
func TestSubstr(t *testing.T) {
    str := "abcdefghijklmn"
    fmt.Println(Substr(str, 0, 3))
    fmt.Println(Substr(str, 1, 3))
    fmt.Println(Substr(str, 1, -1))
}

结果

代码语言:txt复制
=== RUN   TestSubstr
abc
bcd
bcdefghijklmn
--- PASS: TestSubstr (0.00s)
PASS

7. Strrev 翻转字符串

源码

代码语言:go复制
func Strrev(str string) string {
    runes := []rune(str)
    runesLen := len(runes)

    for i := 0; i < runesLen/2; i   {
        runes[i], runes[runesLen-1-i] = runes[runesLen-1-i], runes[i]
    }

    return string(runes)
}

测试

代码语言:go复制
func TestStrrev(t *testing.T) {
    fmt.Println(Strrev("abcd"))
    fmt.Println(Strrev("hi abc"))
    fmt.Println(Strrev("123456"))
}

结果

代码语言:txt复制
=== RUN   TestStrrev
dcba
cba ih
654321
--- PASS: TestStrrev (0.00s)
PASS

8. StrShuffle 随机打乱一个字符串

源码

代码语言:go复制
func StrShuffle(str string) string {
    runes := []rune(str)
    runesLen := len(runes)

    // 1.20以后,不需要此行代码
    rand.Seed(time.Now().UnixNano())

    for i := runesLen - 1; i > 0; i-- {
        j := rand.Intn(i   1)
        runes[i], runes[j] = runes[j], runes[i]
    }

    return string(runes)
}

测试

代码语言:go复制
func TestStrShuffle(t *testing.T) {
    fmt.Println(StrShuffle("abcdefg"))
    fmt.Println(StrShuffle("hello world"))
    fmt.Println(StrShuffle("i am zhangsan"))
}

结果

代码语言:txt复制
=== RUN   TestStrShuffle
afdebgc
 oelroldwhl
mzn niaga ahs
--- PASS: TestStrShuffle (0.00s)
PASS
go

0 人点赞