Contents

Go code

Contents

Go 代码片段

go goroutines pool

package main

import (
	"fmt"

	"github.com/sourcegraph/conc/pool"
)

func main() {
	p := pool.New().WithMaxGoroutines(3)
	for i := 1; i <= 5; i++ {
		p.Go(func() {
			fmt.Println(i)
		})
	}
	p.Wait()
}

带ctx 的go goroutines pool

package main

import (
	"context"
	"errors"
	"fmt"

	"github.com/sourcegraph/conc/pool"
)

func main() {
	p := pool.New().
		WithMaxGoroutines(4).
		WithContext(context.Background()).
		WithCancelOnError()
	for i := 0; i < 3; i++ {
		i := i
		p.Go(func(ctx context.Context) error {
			if i == 2 {
				return errors.New("I will cancel all other tasks!")
			}
			<-ctx.Done()
			return nil
		})
	}
	err := p.Wait()
	fmt.Println(err)
	// Output:
	// I will cancel all other tasks!
}

channel

package main

import (
	"fmt"
)

func main() {
	ch := make(chan int, 3)
	// wg := conc.NewWaitGroup()
	go func() {
		for i := 0; i < 1000; i++ {
			ch <- i
		}
		close(ch)
	}()
	// wg.Wait()

	for v := range ch {
		fmt.Println(v)
	}

}
package main

import (
	"fmt"

	"github.com/sourcegraph/conc"
)

func main() {
	ch := make(chan int)
	// ch2 := make(chan bool)

	wg := conc.NewWaitGroup()

	wg.Go(func() {
		for i := 0; i < 100; i++ {
			ch <- i
		}
		close(ch)
	})

	for sub := range ch {
		fmt.Println(sub)
	}

}

复杂结构体slice排序

type Person struct {
	Name string
	Age  int
	Book int
}


	people := []Person{
		{"Alice", 30, 5},
		{"Bob", 25, 2},
		{"Charlie", 30, 55},
		{"David", 25, 33},
	}
	// 使用 sort.Slice 进行排序,按年龄升序排列,年龄相同则按book排序
	sort.Slice(people, func(i, j int) bool {
		if people[i].Age == people[j].Age {
			return people[i].Book < people[j].Book
		}
		return people[i].Age < people[j].Age
	})

errorgroup

package main

import (
	"errors"
	"fmt"

	"golang.org/x/sync/errgroup"
)

func main() {
	eg := errgroup.Group{}
	eg.Go(func() error {
		fmt.Println("go1")
		return nil
	})
	eg.Go(func() error {
		fmt.Println("go2")
		err := errors.New("go2 err")
		return err
	})
	err := eg.Wait()
	if err != nil {
		fmt.Println("err =", err)
	}
}

// 带ctx
func main1() {
	eg, ctx := errgroup.WithContext(context.Background())
	eg.Go(func() error {
		time.Sleep(1 * time.Second)
		select {
		case <-ctx.Done():
			fmt.Println("go1 cancel, err = ", ctx.Err())
		default:
			fmt.Println("go1 run")
		}
		return nil
	})
	eg.Go(func() error {
		err := errors.New("go2 err")
		return err
	})
	err := eg.Wait()
	if err != nil {
		fmt.Println("err =", err)
	}
}

// 限制并发数
func main2() {
	eg := errgroup.Group{}
	eg.SetLimit(2)
	eg.TryGo(func() error {
		fmt.Println("go1 run")
		return nil
	})
	eg.TryGo(func() error {
		err := errors.New("go2 err")
		return err
	})
	eg.TryGo(func() error {
		fmt.Println("go3 run")
		return nil
	})
	err := eg.Wait()
	if err != nil {
		fmt.Println("err =", err)
	}
}

gorm clause

	err = pa.WithContext(ctx).Clauses(
		clause.OnConflict{
			Columns: []clause.Column{
				{Name: user.Code.ColumnName().String()},
			},
			TargetWhere: clause.Where{
				Exprs: []clause.Expression{
					clause.Expr{
						SQL: "deleted_at = 0",
					},
				},
			},
			DoUpdates: clause.AssignmentColumns(cols),
		},
	).
		CreateInBatches(items, 30)


// 表设计优化,这样只有当deleted_at为null的时候,才会触发code的唯一性校验
// create unique index pa_code
//    on pa (code) where deleted_at is null;

recover 使用

func main3() {
	defer func() {
		if err2 := recover(); err2 != nil {
			fmt.Printf("Run panic error: %v", err2)
		}
	}()
	fmt.Println("xxx")
}

func 作为传参

package main

import "fmt"

func apply(x int, y int, f func(int, int) int) int {
	return f(x, y)
}

func sum(a int, b int) int {
	return a + b
}

func main() {

	asum := apply(5, 10, sum)
	fmt.Println(asum)
}


//
func sayHello(name string) func() string {
	return func() string {
		return "Hello, " + name
	}
}
func main2() {
	hello := sayHello("Go")
	fmt.Println(hello()) // 输出: Hello, Go
}

单元测试

package main

import (
	"testing"
)

func TestInit(t *testing.T) {
	t.Log("heh")

	helper := PersonHelper{}
	helper.init("pleuvoir")
	t.Log(helper.Name)
}

函数运行时间

func TimeSince(f func()) string {
  start := time.Now() // 获取当前时间
  f()                 // 执行传入的函数
  // 获取结束的时间
  elapsed := time.Since(start)
  str := fmt.Sprintf("该函数执行完成耗时:%v", elapsed)
  return str
}

func main() {
  result := TimeSince(timeTest)
  fmt.Println(result)
}

func timeTest() {
  // 运行的函数
  sum := 0
  for i := 0; i < 1111111111; i++ {
    sum++
  }
}

随机数

//start 10,end 20,将获得这之间的随机数
func RandomSum(start int, end int) int {
  // 以当前时间戳作为种子,确保每次生成的随机数都不同
  rand.Seed(time.Now().Unix())
  // 生成一个指定范围之间的随机整数

  randomInt := rand.Intn(end-start+1) + start
  return randomInt
}

生成随机字符串

const (
  letterBytes  = "abcdefghijklmnopqrstuvwxyz"
  capitalBytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  numberBytes  = "0123456789"
  symbolBytes  = "!@#$%^&*()"
)

func RandStringBytes(n int, randomString string) string {
  rand.Seed(time.Now().Unix())
  b := make([]byte, n)
  for i := range b {
    b[i] = randomString[rand.Intn(len(randomString))]
  }
  return string(b)
}

func main() {
//传入随机字符串的长度,以及需要随机那些字符串
  randomString := RandStringBytes(10, letterBytes+numberBytes)
  fmt.Println(randomString)
}

url 解析

func main() {
  // 要解析的 URL 字符串
  urlString := "https://www.example.com/path/to/resource?key1=value1&key2=value2#fragment"

  // 解析 URL 字符串
  parsedUrl, err := url.Parse(urlString)
  if err != nil {
    panic(err)
  }

  // 输出解析后的 URL 的各个部分
  fmt.Println("Scheme:", parsedUrl.Scheme)
  fmt.Println("Host:", parsedUrl.Host)
  fmt.Println("Path:", parsedUrl.Path)
  fmt.Println("RawQuery:", parsedUrl.RawQuery)
  fmt.Println("Fragment:", parsedUrl.Fragment)

  // 解析 URL 的查询参数
  query := parsedUrl.Query()
  fmt.Println("key1:", query.Get("key1"))
  fmt.Println("key2:", query.Get("key2"))
}

执行系统命令

// RunCMD 标准正确错误输出到标准正确输出
func RunCMD(str string, workDir ...string) (string, error) {
	cmd := exec.Command("/bin/bash", "-c", str)
	if len(workDir) > 0 {
		cmd.Dir = workDir[0]
	}
	result, err := cmd.CombinedOutput()
	if err != nil {
		return string(result), err
	}
	return string(result), nil
}

web 文件服务

func main() {
  http.Handle("/", http.FileServer(http.Dir(".")))
  http.ListenAndServe(":8082", nil)
}

排序

	people := []Person{
		{"Alice", 30},
		{"Bob", 25},
		{"Charlie", 35},
	}

// 排序
	sort.Slice(people, func(i, j int) bool {
		return people[i].Age < people[j].Age
	})


// 按多个字段排序,先年龄后name
    sort.Slice(people, func(i, j int) bool {
        if people[i].Age == people[j].Age {
            return people[i].Name < people[j].Name
        }
        return people[i].Age < people[j].Age
    })

// 保持相同元素的原始顺序
    sort.SliceStable(people, func(i, j int) bool {
        return people[i].Age < people[j].Age
    })



// slices.SortFunc 排序
	slices.SortFunc(people, func(a, b Person) int {
		if a.Age != b.Age {
			return a.Age - b.Age
		}
		if a.Name < b.Name {
			return -1
		}
		if a.Name > b.Name {
			return 1
		}
		return 0
	})


// 按另一个list排序
// SortByOrder 根据 orderList 的顺序对 data 进行排序。
// keyFn 用于从元素中提取用于匹配的键。
func SortByOrder[T any, K comparable](
	data []T,
	orderList []K,
	keyFn func(T) K,
) {
	// 构建顺序映射表
	orderMap := make(map[K]int, len(orderList))
	for i, v := range orderList {
		orderMap[v] = i
	}

	// 排序
	sort.SliceStable(data, func(i, j int) bool {
		ki := keyFn(data[i])
		kj := keyFn(data[j])

		oi, okI := orderMap[ki]
		oj, okJ := orderMap[kj]

		switch {
		case okI && okJ:
			return oi < oj
		case okI:
			return true
		case okJ:
			return false
		default:
			return false // 保持原始顺序(稳定排序)
		}
	})
}

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

	SortByOrder(data, order, func(v int) int {
		return v
	})
package utils

import "slices"

func SortByOrderFunc[T any, K comparable](
	data []T,
	orderList []K,
	keyFn func(T) K,
) {
	orderMap := make(map[K]int, len(orderList))
	for i, v := range orderList {
		orderMap[v] = i
	}

	slices.SortStableFunc(data, func(a, b T) int {
		ka := keyFn(a)
		kb := keyFn(b)

		oa, okA := orderMap[ka]
		ob, okB := orderMap[kb]

		switch {
		case okA && okB:
			return oa - ob
		case okA:
			return -1
		case okB:
			return 1
		default:
			return 0
		}
	})
}

list 生成map

type abc struct {
	A string
}
aa := []*abc{}
lo.KeyBy(aa, func(item *abc) string {
	return item.A
})

list 生成map,value为list

// 生成 map  map[string][]*abc{}
lo.GroupBy(aa, func(item *abc) string {
	return item.A
})

根据条件过滤list

even := lo.Filter([]int{1, 2, 3, 4}, func(x int, index int) bool {
    return x%2 == 0
})
// []int{2, 4}

for 循环

lo.ForEach([]string{"hello", "world"}, func(x string, _ int) {
    fmt.Println(x)
})

统计list里某个元素个数

count := lo.Count([]int{1, 5, 1}, 1)
// 2

统计满足条件的元素个数

count := lo.CountBy([]int{1, 5, 1}, func(i int) bool {
    return i < 4
})

统计元素个数,生成map

lo.CountValues([]int{1, 2})
// map[int]int{1: 1, 2: 1}

获取map的key

// 获取map的key
keys := lo.Keys(map[string]int{"foo": 1, "bar": 2})
// []string{"foo", "bar"}

// 获取多个map的key的唯一值,组成唯一的slice
keys := lo.UniqKeys(map[string]int{"foo": 1, "bar": 2}, map[string]int{"baz": 3})
// []string{"foo", "bar", "baz"}

获取map的value

// 获取map的值
values := lo.Values(map[string]int{"foo": 1, "bar": 2})
// []int{1, 2}

// 获取map的值并去重
values := lo.UniqValues(map[string]int{"foo": 1, "bar": 2})
// []int{1, 2}

list 转换

// 切片类型转换
lo.Map([]int64{1, 2, 3, 4}, func(x int64, index int) string {
    return strconv.FormatInt(x, 10)
})

list交集

lo.Intersect([]int64{1, 2, 3, 4},[]int64{1, 2, 6, 4})

list差集

left, right := lo.Difference([]int{0, 1, 2, 3, 4, 5}, []int{0, 2, 6})
// []int{1, 3, 4, 5}, []int{6}

并集

union := lo.Union([]int{0, 1, 2, 3, 4, 5}, []int{0, 2}, []int{0, 10})
// []int{0, 1, 2, 3, 4, 5, 10}

try语法

// 基本用法
ok := lo.Try(func() error {
    return nil
})
// true

json转字符串

func Marshal(data any) (str string) {
	bt, _ := json.Marshal(data)
	return string(bt)
}

func MarshalIndent(data any) (str string) {
	bt, _ := json.MarshalIndent(data, "", "  ")
	return string(bt)
}

多选参数

package main

import "fmt"


type DataBaseConfig struct {
	IP       string
	Port     string
	Db       int
	UserName string
	PassWord string
}

const (
	PassWord = "asd@123"
	UserName = "test"
	Db       = 1
)

type DatabaseOptions func(*DataBaseConfig)

// 添加数据库DB
func WithDb(db int) DatabaseOptions {
	return func(con *DataBaseConfig) {
		con.Db = db
	}
}

// 添加用户名和密码
func WithUserNamePassWord(userName, passWord string) DatabaseOptions {
	return func(con *DataBaseConfig) {
		con.UserName = userName
		con.PassWord = passWord
	}
}

// 可以设置默认参数
func DefaultDatabaseConfig(con *DataBaseConfig) *DataBaseConfig {
	con.PassWord = PassWord
	con.UserName = UserName
	con.Db = Db
	return con
}

func NewDataBaseConnect(IP, Port string, options ...DatabaseOptions) *DataBaseConfig {
	// 本初始化方案,要自己填IP,其他参数可填可不填,也可以使用默认参数
	con := &DataBaseConfig{
		IP:   IP,
		Port: Port,
	}
	// 默认值的设定
	con = DefaultDatabaseConfig(con)

	// 遍历可选参数,然后分别调用匿名函数,将连接对象指针传入,进行修改
	for _, op := range options {
		// 遍历调用函数,进行数据修改
		op(con)
	}
	return con
}

func main() {
	// 传入自定义参数测试可选参数的输入
	var options = []DatabaseOptions{
		WithDb(2),
		WithUserNamePassWord("hello", "passWord"),
	}
	con1 := NewDataBaseConnect("127.0.0.1", "27017", options...)
	fmt.Printf("%#v", con1)

	// 不输入可选参数的测试
	con := NewDataBaseConnect("127.0.0.1", "27017")
	fmt.Printf("%#v", con)
}

接口

package main

import "fmt"

// 定义接口
type Speaker interface {
	Speak() string
}

// 定义结构体并实现接口方法
type Person struct {
	Name string
}

func (p Person) Speak() string {
	return "Hello, my name is " + p.Name
}

type Dog struct{}

func (d Dog) Speak() string {
	return "Woof!"
}

// 使用接口类型的变量
func saySomething(s Speaker) {
	fmt.Println(s.Speak())
}

func main() {
	person := Person{Name: "John"}
	dog := Dog{}

	saySomething(person)
	saySomething(dog)
}

并发安全map

package main

import (
	"fmt"
	"sync"
)

// 进程阻塞
func main() {
	var m sync.Map
	m.Store("userId", 1001)
	m.Store("vvvv", "hello")

	val, ok := m.Load("userId")
	if ok {
		fmt.Println(val)
	}
}

生成tree


func BuildTreePtr[T any, K comparable](
	list []T,
	getID func(*T) K,
	getParentID func(*T) K,
	getChildren func(*T) []*T,
	setChildren func(*T, []*T),
	rootID K,
) []*T {

	nodeMap := make(map[K]*T)
	var result []*T

	// 1. 建立 map
	for i := range list {
		node := &list[i]
		nodeMap[getID(node)] = node
	}

	// 2. 构建树
	for _, node := range nodeMap {
		pid := getParentID(node)
		if pid == rootID {
			result = append(result, node)
		} else {
			if parent, ok := nodeMap[pid]; ok {
				currentChildren := getChildren(parent)
				setChildren(parent, append(currentChildren, node))
			}
		}
	}

	return result
}




// tree验证代码

type Category struct {
	ID       int
	ParentID int
	Name     string
	Children []*Category
}

func main() {
	list := []Category{
		{ID: 1, ParentID: 0, Name: "根"},
		{ID: 2, ParentID: 1, Name: "A"},
		{ID: 3, ParentID: 1, Name: "B"},
		{ID: 4, ParentID: 2, Name: "A-1"},
	}

	tree := BuildTreePtr(
		list,
		func(c *Category) int { return c.ID },
		func(c *Category) int { return c.ParentID },
		func(c *Category) []*Category { return c.Children },
		func(c *Category, children []*Category) { c.Children = children },
		0,
	)

	println(tree)
}

带深度版树

func BuildTreePtrWithDepth[T any, K comparable](
	list []T,
	getID func(*T) K,
	getParentID func(*T) K,
	getChildren func(*T) []*T,
	setChildren func(*T, []*T),
	rootID K,
	maxDepth int,
) []*T {

	nodeMap := make(map[K]*T)
	depthMap := make(map[K]int)
	var result []*T

	// 1. 建立 map
	for i := range list {
		node := &list[i]
		nodeMap[getID(node)] = node
	}

	// 2. 构建树
	for _, node := range nodeMap {
		pid := getParentID(node)
		if pid == rootID {
			result = append(result, node)
			depthMap[getID(node)] = 0
		} else {
			if parent, ok := nodeMap[pid]; ok {
				parentDepth, hasDepth := depthMap[getID(parent)]
				if hasDepth && parentDepth < maxDepth-1 {
					currentChildren := getChildren(parent)
					setChildren(parent, append(currentChildren, node))
					depthMap[getID(node)] = parentDepth + 1
				}
			}
		}
	}

	return result
}

slog 日志封装

package main

import (
        "log/slog"
        "os"
        "path/filepath"
)

func main() {
        logLevel := "info"

        klog := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
                AddSource: true,
                ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
                        if a.Key == slog.SourceKey {
                                source := a.Value.Any().(*slog.Source)
                                source.File = filepath.Base(source.File)
                                return slog.Attr{Key: a.Key, Value: a.Value}
                        }
                        return a
                },
                Level: func() slog.Level {
                        switch logLevel {
                        case "debug":
                                return slog.LevelDebug
                        case "info":
                                return slog.LevelInfo
                        case "warn":
                                return slog.LevelWarn
                        case "error":
                                return slog.LevelError
                        default:
                                return slog.LevelInfo
                        }
                }(),
        }))

        klog.Error("Error log")
        klog.Warn("Warn log")
        klog.Info("Hello, World!")
        klog.Debug("Debug log")

}