ZetCode

Go Lancet

最后修改时间 2024 年 4 月 11 日

在本文中,我们将展示如何使用 lancet 实用库。

Lancet

Lancet 是一个全面、高效且可重用的 Go 编程语言实用函数库。它包含 600 多个函数。Lancet 涵盖了字符串、切片、日期时间、网络、zip、系统、元组或数据结构等各个领域。

系统功能

在 system 包中,我们提供了一些与系统相关的函数。

main.go
package main

import (
    "fmt"

    "github.com/duke-git/lancet/v2/system"
)

func main() {

    res := system.GetOsEnv("JAVA_HOME")
    fmt.Println(res)

    fmt.Println("----------------------------")

    stdout, stderr, err := system.ExecCommand("ls")

    fmt.Println(stdout)
    fmt.Println(stderr)
    fmt.Println(err)

    fmt.Println("----------------------------")

    if system.IsLinux() {
        fmt.Println("OS is Linux")
    } else if system.IsWindows() {
        fmt.Println("OS is Windows")
    } else if system.IsMac() {
        fmt.Println("OS is Mac")
    } else {
        fmt.Println("Unknown OS")
    }
}

本示例检索环境变量,运行命令,并确定操作系统。

res := system.GetOsEnv("JAVA_HOME")
fmt.Println(res)

使用 GetOsEnv 函数,我们可以检索 JAVA_HOME 目录(如果存在)。

stdout, stderr, err := system.ExecCommand("ls")

我们使用 ExecCommand 运行 ls 命令。

if system.IsLinux() {
    fmt.Println("OS is Linux")
} else if system.IsWindows() {
    fmt.Println("OS is Windows")
} else if system.IsMac() {
    fmt.Println("OS is Mac")
} else {
    fmt.Println("Unknown OS")
}

我们使用 IsLinuxIsWindowsIsMac 函数检查运行的操作系统。

$ go run main.go
C:\Users\Jano\.jdks\coretto-17.0.7_7
----------------------------

    Directory: C:\Users\Jano\Documents\prog\go\lancet\system

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----       23. 9. 2023     15:26            167 go.mod
-a----       23. 9. 2023     15:26           2941 go.sum
-a----       23. 9. 2023     15:27            596 main.go

<nil>
------------------
OS is Windows

元组函数

Lancet 支持元组。

main.go
package main

import (
    "fmt"

    "github.com/duke-git/lancet/v2/tuple"
)

func main() {
    t := tuple.NewTuple2(1, 0.1)

    x, y := t.Unbox()

    fmt.Println(x)
    fmt.Println(y)

    fmt.Printf("%v %v", t.FieldA, t.FieldB)

    t2 := tuple.NewTuple3(1, 0.1, "a")
    fmt.Printf("%v %v %v", t2.FieldA, t2.FieldB, t2.FieldC)

    a, b, c := t2.Unbox()
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}

本示例定义并解包了两个元素和三个元素的元组。

$ go run main.go
1
0.1
1 0.11 0.1 a1
0.1
a

日期和时间函数

datetime 包中,我们提供了一些与日期和时间相关的函数。

main.go
package main

import (
    "fmt"
    "time"

    "github.com/duke-git/lancet/v2/datetime"
)

func main() {

    now := time.Now()

    dt := datetime.AddYear(now, 11)
    fmt.Println(dt)
    fmt.Println(datetime.FormatTimeToStr(dt, "yyyy-mm-dd"))

    res2 := datetime.EndOfYear(now)
    fmt.Println(res2)

    begin := datetime.BeginOfWeek(now)
    fmt.Println(begin)
}

本示例展示了 AddYearFormatTimeToStrEndOfYearBeginOfWeek 函数。

$ go run main.go
2034-09-20 15:45:35.7624076 +0200 CEST m=+346896000.002289001
2034-09-20
2023-12-31 23:59:59.999999999 +0100 CET
2023-09-17 00:00:00 +0200 CEST

切片函数

在下一个示例中,我们将展示一些切片函数。

main.go
package main

import (
    "fmt"

    "github.com/duke-git/lancet/v2/slice"
    "github.com/duke-git/lancet/v2/strutil"
)

func main() {
    vals := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    n1 := slice.CountBy(vals, isEven)
    fmt.Println(n1)

    words := []string{"sky", "war", "blue", "war", "cottage",
        "war", "car", "pen", "book"}

    n2 := slice.Count(words, "war")
    fmt.Println(n2)

    fmt.Println("------------------------------")

    shuffled := slice.Shuffle(vals)
    slice.ForEach(shuffled, func(_, e int) { fmt.Println(e) })

    fmt.Println("------------------------------")

    res := slice.Map(vals, func(_, e int) int { return e * 2 })
    fmt.Println(res)

    res2 := slice.Map(words, func(_ int, e string) string { return strutil.UpperFirst(e) })
    fmt.Println(res2)
}

本示例使用了 CountByCountShuffleMapForEach 切片函数。

vals := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}

isEven := func(i, num int) bool {
    return num%2 == 0
}

n1 := slice.CountBy(vals, isEven)

使用 CountBy,我们计算 isEven predicate 返回 true 的切片元素的数量。

words := []string{"sky", "war", "blue", "war", "cottage",
    "war", "car", "pen", "book"}

n2 := slice.Count(words, "war")

我们计算 words 切片中 war 单词的出现次数。

shuffled := slice.Shuffle(vals)
slice.ForEach(shuffled, func(_, e int) { fmt.Println(e) })

我们使用 Shuffle 随机排列 vals 切片,并使用 ForEach 遍历它。

res := slice.Map(vals, func(_, e int) int { return e * 2 })
fmt.Println(res)

使用 Map,我们将给定的匿名函数应用于切片中的每个元素。

$ go run main.go
5
3
------------------------------
6
10
11
9
7
2
1
5
3
4
8
------------------------------
[12 20 22 18 14 4 2 10 6 8 16]
[Sky War Blue War Cottage War Car Pen Book]

网络函数

我们提供了一些网络相关的函数。

main.go
package main

import (
    "fmt"
    "log"

    "github.com/duke-git/lancet/v2/netutil"
)

type Post struct {
    UserId int    `json:"userId"`
    Id     int    `json:"id"`
    Title  string `json:"title"`
    Body   string `json:"body"`
}

func main() {
    req := &netutil.HttpRequest{
        RawURL: "https://jsonplaceholder.typicode.com/posts/1",
        Method: "GET",
    }

    client := netutil.NewHttpClient()
    resp, err := client.SendRequest(req)

    if err != nil || resp.StatusCode != 200 {
        log.Fatal(err)
    }

    var body Post
    err = client.DecodeResponse(resp, &body)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(body)

    fmt.Println("-------------------------")

    fmt.Println(body.Id)
    fmt.Println(body.UserId)
    fmt.Println(body.Title)
    fmt.Println(body.Body)
}

本示例从在线测试服务检索一个帖子。

req := &netutil.HttpRequest{
    RawURL: "https://jsonplaceholder.typicode.com/posts/1",
    Method: "GET",
}

我们定义了一个 HTTP GET 请求。

client := netutil.NewHttpClient()
resp, err := client.SendRequest(req)

创建了一个 HTTP 客户端并发送了一个新请求。

if err != nil || resp.StatusCode != 200 {
    log.Fatal(err)
}

我们检查响应状态和错误。

var body Post
err = client.DecodeResponse(resp, &body)
if err != nil {
    log.Fatal(err)
}

我们将 JSON 响应解码到 Post 结构体正文中。

排序函数

algorithm 包包含一些排序算法。

在下一个示例中,我们使用快速排序算法。

main.go
package main

import (
    "fmt"

    "github.com/duke-git/lancet/v2/algorithm"
)

type intComparator struct{}

func (c *intComparator) Compare(e1 any, e2 any) int {
    val1, _ := e1.(int)
    val2, _ := e2.(int)

    if val1 < val2 {
        return -1
    } else if val1 > val2 {
        return 1
    }
    return 0
}

func main() {

    vals := []int{2, 1, 5, 3, 6, 4, -2, 0, 9, 11, -3}
    
    comparator := &intComparator{}
    algorithm.QuickSort(vals, comparator)

    fmt.Println(vals)
}

本示例使用快速排序算法对切片中的整数进行排序。

type intComparator struct{}

func (c *intComparator) Compare(e1 any, e2 any) int {
    val1, _ := e1.(int)
    val2, _ := e2.(int)

    if val1 < val2 {
        return -1
    } else if val1 > val2 {
        return 1
    }
    return 0
}

我们定义了 Compare 函数。

comparator := &intComparator{}
algorithm.QuickSort(vals, comparator)

我们使用 QuickSort 对数字进行排序。

$ go run main.go
[-3 -2 0 1 2 3 4 5 6 9 11]

下面的示例使用插入排序算法。

main.go
package main

import (
    "fmt"

    "github.com/duke-git/lancet/v2/algorithm"
)

type User struct {
    Name string
    Age  int
}

type byAge struct{}

func (c *byAge) Compare(u1 any, u2 any) int {
    p1, _ := u1.(User)
    p2, _ := u2.(User)

    if p1.Age < p2.Age {
        return -1
    } else if p1.Age > p2.Age {
        return 1
    }

    return 0
}

func main() {
    users := []User{
        {Name: "Peter", Age: 20},
        {Name: "Julia", Age: 14},
        {Name: "Lucia", Age: 17},
        {Name: "Roman", Age: 18},
        {Name: "Jan", Age: 28},
    }

    comparator := &byAge{}
    algorithm.InsertionSort(users, comparator)

    fmt.Println(users)
}

本示例使用 InsertionSort 按年龄对用户进行排序。

func (pc *byAge) Compare(u1 any, u2 any) int {
    p1, _ := u1.(User)
    p2, _ := u2.(User)

    if p1.Age < p2.Age {
        return -1
    } else if p1.Age > p2.Age {
        return 1
    }

    return 0
}

我们定义了 Compare 函数。

comparator := &byAge{}
algorithm.InsertionSort(users, comparator)

我们使用 InsertionSort 对用户进行就地排序。

$ go run main.go
[{Julia 14} {Lucia 17} {Roman 18} {Peter 20} {Jan 28}]

字符串函数

字符串函数位于 strutil 包中。

main.go
package main

import (
    "fmt"

    "github.com/duke-git/lancet/v2/strutil"
)

func main() {

    msg := "an old falcon"

    fmt.Println(strutil.CamelCase(msg))
    fmt.Println(strutil.Capitalize(msg))
    fmt.Println(strutil.KebabCase(msg))

    fmt.Println(strutil.UpperFirst(msg))
    fmt.Println(strutil.SnakeCase(msg))
    fmt.Println(strutil.Reverse(msg))
}

本示例使用六个不同的函数修改一个字符串。

$ go run main.go
anOldFalcon
An old falcon
an-old-falcon
An old falcon
an_old_falcon
noclaf dlo na

接下来我们使用另外 4 个函数。

main.go
package main

import (
    "fmt"

    "github.com/duke-git/lancet/v2/strutil"
)

func main() {

    msg := "F# мультипарадигмальный язык программирования из семейства языков .NET."
    fmt.Println(strutil.WordCount(msg))
    fmt.Println(strutil.IsString(msg))

    w1 := "\t"
    w2 := "  "
    w3 := "."

    fmt.Println(strutil.IsBlank(w1))
    fmt.Println(strutil.IsBlank(w2))
    fmt.Println(strutil.IsBlank(w3))

    fmt.Println(strutil.IsBlank(strutil.Trim(w1)))
}

在下一个示例中,我们计算字符串中的单词数,并使用 IsStringIsBlank 检查值,并使用 Trim 修剪字符串。

$ go run main.go
8
true
true
true
false
true

Function 包

function 包可以控制函数执行流程,并为函数式编程提供一些支持。

main.go
package main

import (
    "fmt"

    "github.com/duke-git/lancet/v2/function"
    "github.com/duke-git/lancet/v2/slice"
)

func double(vals []int) []int {
    return slice.Map(vals, func(_, e int) int { return e * 2 })
}

func incByOne(vals []int) []int {
    return slice.Map(vals, func(_, e int) int { return e + 1 })
}

func main() {

    vals := []int{1, 2, 3, 4, 5}

    transform := function.Pipeline(double, incByOne)
    res := transform(vals)

    fmt.Println(res)
}

在本示例中,我们调用 Pipeline 将两个函数管道化到 vals 切片上。

func double(vals []int) []int {
    return slice.Map(vals, func(_, e int) int { return e * 2 })
}

func incByOne(vals []int) []int {
    return slice.Map(vals, func(_, e int) int { return e + 1 })
}

我们有两个函数,它们将切片元素加倍并递增。

transform := function.Pipeline(double, incByOne)

我们创建了一个由这两个函数组成的管道。

res := transform(vals)

管道被执行。

$ go run main.go 
[3 5 7 9 11]

Zip

fileutil 包包含一个 Zip 函数,用于创建 ZIP 存档。

main.go
package main

import (
    "fmt"

    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    err := fileutil.Zip(".", "current.zip")
    if err != nil {
        fmt.Println(err)
    }
}

本示例从当前工作目录创建了一个 ZIP 存档。

来源

Go Lancet - Github 页面

在本文中,我们使用了 lancet 实用库。

作者

我叫 Jan Bodnar,是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程