All skills
gogf avatar

/goframe-v2

@911705d
by GoFramegogf/skills81 stars
3

GoFrame v2 development skill. Use only when the target Go project uses or is explicitly adopting GoFrame v2: the nearest go.mod requires github.com/gogf/gf/v2, existing Go files import github.com/gogf/gf/v2 or any github.com/gogf/gf/v2/... component package, or the user asks to scaffold, migrate, or build with GoFrame. Trigger for GoFrame-backed Go work such as APIs/controllers/services, middleware, routing/config, ORM/DAO/DO/entity/database operations, gf CLI/codegen, HTTP/gRPC services, and microservice conventions. Do not trigger for generic Go projects without GoFrame evidence, frontend-only work, shell scripts, or unrelated infrastructure tasks.

Use this Skill: https://skilld.dev/gh/gogf/skills/goframe-v2

This session only. Nothing lands on disk.

references组件列表数据结构数组类型-garray数组类型-基本使用.md

泛型数组(推荐使用)

从v2.10版本开始,garray提供了泛型数组TArray[T]和SortedTArray[T],提供类型安全的数组操作,避免类型断言和运行时错误,享受编译时类型检查带来的安全性。

泛型普通数组TArray

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
)

func main() {
    // 创建int类型的泛型数组
    intArr := garray.NewTArray[int]()
    intArr.Append(10)
    intArr.Append(20)
    intArr.Append(15)
    intArr.Append(30)
    fmt.Println(intArr.Slice())

    // 创建string类型的泛型数组
    strArr := garray.NewTArray[string]()
    strArr.Append("We")
    strArr.Append("are")
    strArr.Append("GF")
    strArr.Append("fans")
    fmt.Println(strArr.Slice())
}

执行后,输出结果为:

[10 20 15 30]
[We are GF fans]

泛型排序数组SortedTArray

泛型排序数组需要传入一个比较函数,用于定义元素的排序规则。gutil包提供了常用的比较函数ComparatorT。

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/util/gutil"
)

func main() {
    // 创建字符串类型的排序数组(升序)
    s := garray.NewSortedTArray[string](gutil.ComparatorT)
    s.Append("b")
    s.Append("d")
    s.Append("c")
    s.Append("a")
    fmt.Println(s.Slice())

    // 创建自定义比较函数的降序排序数组
    intArr := garray.NewSortedTArray[int](func(a, b int) int {
        if a > b {
            return -1
        }
        if a < b {
            return 1
        }
        return 0
    })
    intArr.Append(2)
    intArr.Append(3)
    intArr.Append(1)
    fmt.Println(intArr.Slice())
}

执行后,输出结果为:

[a b c d]
[3 2 1]

泛型数组特点

泛型数组具有以下特点:

  1. 类型安全:在编译期就能发现类型错误,避免运行时类型转换失败。
  2. 更好的IDE支持:IDE能够提供更准确的代码补全和类型提示。
  3. 性能优势:减少了类型断言的开销。
  4. 与旧版本兼容:泛型数组与传统的Array、IntArray、StrArray等类型可以共存。

:::tip 推荐在新项目中使用泛型数组 TArray[T] 和 SortedTArray[T],它们提供了更好的类型安全性和开发体验。 :::

传统数组类型

下面介绍传统的数组类型,这些类型在旧版本中被广泛使用,仍然完全支持。

普通数组

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
)

func main () {
    // 创建并发安全的int类型数组
    a := garray.NewIntArray(true)

    // 添加数据项
    for i := 0; i < 10; i++ {
        a.Append(i)
    }

    // 获取当前数组长度
    fmt.Println(a.Len())

    // 获取当前数据项列表
    fmt.Println(a.Slice())

    // 获取指定索引项
    fmt.Println(a.Get(6))

    // 在指定索引后插入数据项
    a.InsertAfter(9, 11)
    // 在指定索引前插入数据项
    a.InsertBefore(10, 10)
    fmt.Println(a.Slice())

    // 修改指定索引的数据项
    a.Set(0, 100)
    fmt.Println(a.Slice())

    // 搜索数据项,返回搜索到的索引位置
    fmt.Println(a.Search(5))

    // 删除指定索引的数据项
    a.Remove(0)
    fmt.Println(a.Slice())

    // 并发安全,写锁操作
    a.LockFunc(func(array []int) {
        // 将末尾项改为100
        array[len(array) - 1] = 100
    })

    // 并发安全,读锁操作
    a.RLockFunc(func(array []int) {
        fmt.Println(array[len(array) - 1])
    })

    // 清空数组
    fmt.Println(a.Slice())
    a.Clear()
    fmt.Println(a.Slice())
}

执行后,输出结果为:

[0 1 2 3 4 5 6 7 8 9]
6 true
[0 1 2 3 4 5 6 7 8 9 10 11]
[100 1 2 3 4 5 6 7 8 9 10 11]
5
[1 2 3 4 5 6 7 8 9 10 11]
100
[1 2 3 4 5 6 7 8 9 10 100]
[]

排序数组

排序数组的方法与普通数组类似,但是带有自动排序功能及唯一性过滤功能。

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
)

func main () {
    // 自定义排序数组,降序排序(SortedIntArray管理的数据是升序)
    a := garray.NewSortedArray(func(v1, v2 interface{}) int {
        if v1.(int) < v2.(int) {
            return 1
        }
        if v1.(int) > v2.(int) {
            return -1
        }
        return 0
    })

    // 添加数据
    a.Add(2)
    a.Add(3)
    a.Add(1)
    fmt.Println(a.Slice())

    // 添加重复数据
    a.Add(3)
    fmt.Println(a.Slice())

    // 检索数据,返回最后对比的索引位置,检索结果
    // 检索结果:0: 匹配; <0:参数小于对比值; >0:参数大于对比值
    fmt.Println(a.Search(1))

    // 设置不可重复
    a.SetUnique(true)
    fmt.Println(a.Slice())
    a.Add(1)
    fmt.Println(a.Slice())
}

执行后,输出结果:

[3 2 1]
[3 3 2 1]
3 0
[3 2 1]
[3 2 1]

Iterate* 数组遍历

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    array := garray.NewStrArrayFrom(g.SliceStr{"a", "b", "c"})
    // Iterator is alias of IteratorAsc, which iterates the array readonly in ascending order
    //  with given callback function <f>.
    // If <f> returns true, then it continues iterating; or false to stop.
    array.Iterator(func(k int, v string) bool {
        fmt.Println(k, v)
        return true
    })
    // IteratorDesc iterates the array readonly in descending order with given callback function <f>.
    // If <f> returns true, then it continues iterating; or false to stop.
    array.IteratorDesc(func(k int, v string) bool {
        fmt.Println(k, v)
        return true
    })

    // Output:
    // 0 a
    // 1 b
    // 2 c
    // 2 c
    // 1 b
    // 0 a
}

Pop* 数组项出栈

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
)

func main() {
    array := garray.NewFrom([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9})

    // Any Pop* functions pick, delete and return the item from array.

    fmt.Println(array.PopLeft())
    fmt.Println(array.PopLefts(2))
    fmt.Println(array.PopRight())
    fmt.Println(array.PopRights(2))

    // Output:
    // 1 true
    // [2 3]
    // 9 true
    // [7 8]
}

Rand/PopRand 数组项随机获取/出栈

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    array := garray.NewFrom(g.Slice{1, 2, 3, 4, 5, 6, 7, 8, 9})

    // Randomly retrieve and return 2 items from the array.
    // It does not delete the items from array.
    fmt.Println(array.Rands(2))

    // Randomly pick and return one item from the array.
    // It deletes the picked up item from array.
    fmt.Println(array.PopRand())
}

Contains/ContainsI 包含判断

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
)

func main() {
    var array garray.StrArray
    array.Append("a")
    fmt.Println(array.Contains("a"))
    fmt.Println(array.Contains("A"))
    fmt.Println(array.ContainsI("A"))

    // Output:
    // true
    // false
    // true
}

FilterEmpty/FilterNil 空值过滤

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    array1 := garray.NewFrom(g.Slice{0, 1, 2, nil, "", g.Slice{}, "john"})
    array2 := garray.NewFrom(g.Slice{0, 1, 2, nil, "", g.Slice{}, "john"})
    fmt.Printf("%#v\n", array1.FilterNil().Slice())
    fmt.Printf("%#v\n", array2.FilterEmpty().Slice())

    // Output:
    // []interface {}{0, 1, 2, "", []interface {}{}, "john"}
    // []interface {}{1, 2, "john"}
}

Reverse 数组反转

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    array := garray.NewFrom(g.Slice{1, 5, 3})

    // Reverse makes array with elements reverse.
    fmt.Println(array.Reverse().Slice())

    // Output:
    // [3 5 1]
}

Shuffle 随机排序

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    array := garray.NewFrom(g.Slice{1, 2, 3, 4, 5, 6, 7, 8, 9})

    // Shuffle randomly shuffles the array.
    fmt.Println(array.Shuffle().Slice())
}

Walk 遍历修改

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    var array garray.StrArray
    tables := g.SliceStr{"user", "user_detail"}
    prefix := "gf_"
    array.Append(tables...)
    // Add prefix for given table names.
    array.Walk(func(value string) string {
        return prefix + value
    })
    fmt.Println(array.Slice())

    // Output:
    // [gf_user gf_user_detail]
}

Join 数组项串连

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    array := garray.NewFrom(g.Slice{"a", "b", "c", "d"})
    fmt.Println(array.Join(","))

    // Output:
    // a,b,c,d
}

Chunk 数组拆分

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    array := garray.NewFrom(g.Slice{1, 2, 3, 4, 5, 6, 7, 8, 9})

    // Chunk splits an array into multiple arrays,
    // the size of each array is determined by <size>.
    // The last chunk may contain less than size elements.
    fmt.Println(array.Chunk(2))

    // Output:
    // [[1 2] [3 4] [5 6] [7 8] [9]]
}

Merge 数组合并

package main

import (
    "fmt"
    "github.com/gogf/gf/v2/container/garray"
    "github.com/gogf/gf/v2/frame/g"
)

func main() {
    array1 := garray.NewFrom(g.Slice{1, 2})
    array2 := garray.NewFrom(g.Slice{3, 4})
    slice1 := g.Slice{5, 6}
    slice2 := []int{7, 8}
    slice3 := []string{"9", "0"}
    fmt.Println(array1.Slice())
    array1.Merge(array1)
    array1.Merge(array2)
    array1.Merge(slice1)
    array1.Merge(slice2)
    array1.Merge(slice3)
    fmt.Println(array1.Slice())

    // Output:
    // [1 2]
    // [1 2 1 2 3 4 5 6 7 8 9 0]
}

JSON 序列化/反序列

garray 模块下的所有容器类型均实现了标准库 json 数据格式的序列化/反序列化接口。

  1. Marshal
package main

import (
       "encoding/json"
       "fmt"
       "github.com/gogf/gf/v2/container/garray"
)

func main() {
       type Student struct {
           Id     int
           Name   string
           Scores *garray.IntArray
       }
       s := Student{
           Id:     1,
           Name:   "john",
           Scores: garray.NewIntArrayFrom([]int{100, 99, 98}),
       }
       b, _ := json.Marshal(s)
       fmt.Println(string(b))
}

执行后,输出结果:

    {"Id":1,"Name":"john","Scores":[100,99,98]}
  1. Unmarshal
package main

import (
       "encoding/json"
       "fmt"
       "github.com/gogf/gf/v2/container/garray"
)

func main() {
       b := []byte(`{"Id":1,"Name":"john","Scores":[100,99,98]}`)
       type Student struct {
           Id     int
           Name   string
           Scores *garray.IntArray
       }
       s := Student{}
       json.Unmarshal(b, &s)
       fmt.Println(s)
}

执行后,输出结果:

{1 john [100,99,98]}

Source: SKILL.md on GitHub

1 alert16d5 checks · Risk MEDIUM
  • Gen Agent Trust Hub16d

    The skill provides a comprehensive development guide and code examples for the GoFrame v2 framework. While highly informative for Go developers, it contains several examples with hardcoded placeholder secrets, tokens, and specific local file paths to sensitive configuration files (like Kubernetes credentials). These elements are provided for demonstration purposes but represent insecure practices if used in production without modification.

  • Socket16d

    5 alerts: gptSecurity, gptAnomaly

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    227/949 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 911705d. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 4 months ago.

Steadyupdated 4 months ago
  • Go
  • Database
  • goframe
  • orm
  • http
  • grpc
  • microservices
  • crud
  • scaffolding
  • middleware

README badge

README badge for gogf/skills

Provides instruction and conventions for developing with GoFrame v2, a modular Go framework for building HTTP and gRPC services, microservices, and database operations using its ORM, CLI tooling, and project scaffolding. Use this skill when the target project has GoFrame v2 as a dependency or when the user requests scaffolding, migrations, or service development with GoFrame conventions.

Generated from the current SKILL.md.

When should I use this skill?
Use this skill only when your Go project uses GoFrame v2, indicated by github.com/gogf/gf/v2 in go.mod or imports. Do not use for generic Go projects, frontend work, or infrastructure tasks unrelated to GoFrame.
Should I manually set created_at and updated_at fields?
No. GoFrame automatically writes created_at on insert and updated_at on insert/update/save. Manually setting these fields is redundant and violates project conventions.
What should I use for database operations instead of g.Map?
Always use DO objects from internal/model/do/. DO struct fields are interface{}, unset fields remain nil and are automatically ignored by the ORM.
How does soft delete work in GoFrame?
Call Delete() on the DAO; GoFrame automatically converts it to UPDATE SET deleted_at = NOW(). Queries automatically filter out soft-deleted rows without requiring manual WhereNull conditions.
Where should I implement business logic?
Implement business logic directly in the service/ directory. Do not use the logic/ directory unless explicitly requested.

Generated from the current SKILL.md. These answers refresh after source changes.