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核心组件类型转换类型转换-Scan转换.md

前面关于复杂类型的转换功能如果大家觉得还不够的话,那么您可以了解下 Scan 转换方法,该方法可以实现对任意参数到 基础数据类型/struct/struct数组/map/map数组 的转换,并且根据开发者输入的转换目标参数自动识别执行转换。

该方法定义如下:

// Scan automatically checks the type of `pointer` and converts `params` to `pointer`.
// It supports various types of parameter conversions, including:
// 1. Basic types (int, string, float, etc.)
// 2. Pointer types
// 3. Slice types
// 4. Map types
// 5. Struct types
//
// The `paramKeyToAttrMap` parameter is used for mapping between attribute names and parameter keys.
func Scan(srcValue any, dstPointer any, paramKeyToAttrMap ...map[string]string) (err error)

基础数据类型转换

Scan 方法在v2.9版本中增强了对基础数据类型的转换支持,可以将各种类型的值转换为基础数据类型,如 int、string、bool 等。

整数类型转换

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    // 字符串转整数
    var num int
    if err := gconv.Scan("123", &num); err != nil {
        panic(err)
    }
    g.Dump(num) // 输出: 123
    
    // 浮点数转整数
    var num2 int
    if err := gconv.Scan(123.45, &num2); err != nil {
        panic(err)
    }
    g.Dump(num2) // 输出: 123
    
    // 布尔值转整数
    var num3 int
    if err := gconv.Scan(true, &num3); err != nil {
        panic(err)
    }
    g.Dump(num3) // 输出: 1
}

字符串类型转换

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    // 整数转字符串
    var str string
    if err := gconv.Scan(123, &str); err != nil {
        panic(err)
    }
    g.Dump(str) // 输出: "123"
    
    // 浮点数转字符串
    var str2 string
    if err := gconv.Scan(123.45, &str2); err != nil {
        panic(err)
    }
    g.Dump(str2) // 输出: "123.45"
    
    // 布尔值转字符串
    var str3 string
    if err := gconv.Scan(true, &str3); err != nil {
        panic(err)
    }
    g.Dump(str3) // 输出: "true"
}

布尔类型转换

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    // 整数转布尔值
    var b1 bool
    if err := gconv.Scan(1, &b1); err != nil {
        panic(err)
    }
    g.Dump(b1) // 输出: true
    
    // 字符串转布尔值
    var b2 bool
    if err := gconv.Scan("true", &b2); err != nil {
        panic(err)
    }
    g.Dump(b2) // 输出: true
    
    // 0值转布尔值
    var b3 bool
    if err := gconv.Scan(0, &b3); err != nil {
        panic(err)
    }
    g.Dump(b3) // 输出: false
}

指针类型转换

Scan 方法还支持指针类型的转换,可以将值转换为指针类型,或者将指针类型转换为另一个指针类型。

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    // 值转指针
    var numPtr *int
    if err := gconv.Scan(123, &numPtr); err != nil {
        panic(err)
    }
    g.Dump(numPtr)  // 输出: 123 (指针指向的值)
    
    // 指针转指针
    var num = 456
    var numPtr2 *int
    if err := gconv.Scan(&num, &numPtr2); err != nil {
        panic(err)
    }
    g.Dump(numPtr2) // 输出: 456 (指针指向的值)
}

自动识别转换 Struct

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    type User struct {
        Uid  int
        Name string
    }
    params := g.Map{
        "uid":  1,
        "name": "john",
    }
    var user *User
    if err := gconv.Scan(params, &user); err != nil {
        panic(err)
    }
    g.Dump(user)
}

执行后,输出结果为:

{
    Uid:  1,
    Name: "john",
}

自动识别转换 Struct 数组

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    type User struct {
        Uid  int
        Name string
    }
    params := g.Slice{
        g.Map{
            "uid":  1,
            "name": "john",
        },
        g.Map{
            "uid":  2,
            "name": "smith",
        },
    }
    var users []*User
    if err := gconv.Scan(params, &users); err != nil {
        panic(err)
    }
    g.Dump(users)
}

执行后,终端输出:

[
    {
        Uid:  1,
        Name: "john",
    },
    {
        Uid:  2,
        Name: "smith",
    },
]

自动识别转换Map

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    var (
        user   map[string]string
        params = g.Map{
            "uid":  1,
            "name": "john",
        }
    )
    if err := gconv.Scan(params, &user); err != nil {
        panic(err)
    }
    g.Dump(user)
}

执行后,输出结果为:

{
    "uid":  "1",
    "name": "john",
}

自动识别转换 Map 数组

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    var (
        users  []map[string]string
        params = g.Slice{
            g.Map{
                "uid":  1,
                "name": "john",
            },
            g.Map{
                "uid":  2,
                "name": "smith",
            },
        }
    )
    if err := gconv.Scan(params, &users); err != nil {
        panic(err)
    }
    g.Dump(users)
}

执行后,输出结果为:

[
    {
        "uid":  "1",
        "name": "john",
    },
    {
        "uid":  "2",
        "name": "smith",
    },
]

Scan 高级选项(v2.10+)

从 v2.10.0 版本开始,gconv 包新增了 ScanWithOptions 函数,支持更灵活的转换控制选项,特别是 OmitEmpty 和 OmitNil 选项。

方法定义

// ScanWithOptions 自动检查 dstPointer 的类型并将 srcValue 转换为 dstPointer。
// 它与 Scan 函数相同,但接受一个或多个 ScanOption 值以进行额外的转换控制。
//
// 使用 ScanWithOptions 时,"忽略"(omit)意味着跳过从源到目标的赋值,
// 从而保留目标字段中的现有值。
//
//   - option.OmitEmpty,当设置为 true 时,跳过空源值的赋值(例如:空字符串、
//     零数值、零时间值、空切片或映射),保留目标中任何现有的非空值。
//
//   - option.OmitNil,当设置为 true 时,跳过 nil 源值的赋值,
//     当源包含 nil 时保留目标中的现有值。
//
func ScanWithOptions(srcValue any, dstPointer any, option ...ScanOption) (err error)

OmitEmpty 选项

OmitEmpty 选项用于在转换时跳过空值字段的赋值,保留目标结构体中已有的非空值。

什么是空值?

  • 空字符串("")
  • 零数值(0、0.0)
  • 零时间值
  • 空切片或空映射(nil 或长度为0)

使用场景: 当你需要将源数据合并到目标数据中,但不希望源数据中的空值覆盖目标数据中已有的值时,可以使用此选项。

示例:

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    type User struct {
        Name  string
        Age   int
        Email string
    }

    // 目标结构体包含初始值
    person := User{
        Name:  "张三",
        Age:   30,
        Email: "zhangsan@example.com",
    }

    // 源数据包含一些空值
    sourceData := g.Map{
        "Name":  "",     // 空字符串
        "Age":   25,     // 非空值
        "Email": "",     // 空字符串
    }

    // 使用 OmitEmpty 选项进行转换
    err := gconv.ScanWithOptions(sourceData, &person, gconv.ScanOption{
        OmitEmpty: true,
    })
    if err != nil {
        panic(err)
    }

    g.Dump(person)
}

执行后,输出结果为:

{
    Name:  "张三",      // 保持原值,因为源值为空字符串
    Age:   25,          // 更新为源值
    Email: "zhangsan@example.com", // 保持原值,因为源值为空字符串
}

OmitNil 选项

OmitNil 选项用于在转换时跳过 nil 值字段的赋值,保留目标结构体中已有的值。

使用场景: 当你的源数据是 map[string]any 类型,其中可能包含 nil 值,而你不希望这些 nil 值覆盖目标结构体中已有的值时,可以使用此选项。

示例:

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    type Person struct {
        Name  string
        Age   int
        Email string
    }

    // 目标结构体包含初始值
    person := Person{
        Name:  "李四",
        Age:   0,
        Email: "lisi@example.com",
    }

    // 源数据包含 nil 值
    sourceData := map[string]any{
        "Name":  nil,  // nil 值
        "Age":   30,   // 非 nil 值
        "Email": nil,  // nil 值
    }

    // 使用 OmitNil 选项进行转换
    err := gconv.ScanWithOptions(sourceData, &person, gconv.ScanOption{
        OmitNil: true,
    })
    if err != nil {
        panic(err)
    }

    g.Dump(person)
}

执行后,输出结果为:

{
    Name:  "李四",      // 保持原值,因为源值为 nil
    Age:   30,          // 更新为源值
    Email: "lisi@example.com", // 保持原值,因为源值为 nil
}

同时使用 OmitEmpty 和 OmitNil

你可以同时使用这两个选项来实现更灵活的转换控制:

package main

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    type User struct {
        Name  string
        Age   int
        Email string
    }

    // 目标结构体包含初始值
    user := User{
        Name:  "王五",
        Age:   0,
        Email: "wangwu@example.com",
    }

    // 源数据同时包含空值和 nil 值
    sourceData := map[string]any{
        "Name":  "",    // 空字符串
        "Age":   25,    // 非空值
        "Email": nil,   // nil 值
    }

    // 同时使用 OmitEmpty 和 OmitNil 选项
    err := gconv.ScanWithOptions(sourceData, &user, gconv.ScanOption{
        OmitEmpty: true,
        OmitNil:   true,
    })
    if err != nil {
        panic(err)
    }

    g.Dump(user)
}

执行后,输出结果为:

{
    Name:  "王五",      // 保持原值,因为源值为空字符串
    Age:   25,          // 更新为源值
    Email: "wangwu@example.com", // 保持原值,因为源值为 nil
}

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.