0%

Go_中传递参数类型的判定与其他用法

Go_中传递参数类型的判定与其他用法

func SearchDB(DbModel *gorm.DB, Parms map[string]interface{}, SqlKey string, tableOrModel interface{}) interface{} {
// 特别注意 tableOrModel interface{} 表示可以传递任意值
fmt.Println(tableOrModel)
// 验证表名
TableName := "" // 初始化变量 为空字符串
switch v := tableOrModel.(type) { //这里 类型开关(type switch)
case string: //如果 v的类型是 string 那么 TableName=v
TableName = v
case *string: // 如果 v 的类型是指针
if v == nil { // 判定 v 是否为空值
return fmt.Errorf("表名指针不能为空") // 如果 v 的值是空的,返回错误提示 表名不得为空
}
TableName = *v // 否则 TableName = v指针指向的值
default: // 如果以上都不是,默认走的分支
// 尝试从模型获取表名
// 这里拆开看 会清晰一点
// model, ok := v.(interface{ TableName() string })
// 这里定义返回值:v.(interface{ TableName() string }) 其实就是 对 interface{ TableName() string } 进行类型的判断
// .():类型断言操作符
// interface{ TableName() string }:一个接口类型,要求实现 TableName() string 方法

// if ok {TableName = model.TableName()}

if model, ok := v.(interface{ TableName() string }); ok { //interface{ TableName() string },检查是否有 func TableName() string 方法
TableName = model.TableName()
} else {
// 使用反射获取类型名称 详解见下方总结
t := reflect.TypeOf(v) // 获取对象的类型
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
TableName = t.Name()
}
}

if TableName == "" {
return fmt.Errorf("表名不能为空")
}

// 根据操作类型执行相应操作
switch strings.ToLower(SqlKey) {
case "insert":
return handleInsert(DbModel, Parms, TableName)
case "find":
return handleFind(DbModel, Parms, TableName)
case "update":
return handleUpdate(DbModel, Parms, TableName)
default:
return fmt.Errorf("无效的操作类型: %s (支持: insert, find, update)", SqlKey)
}
}

总结

  1. 获取类型对象reflect.TypeOf(v) → 获取类型信息
  2. 检查指针类型t.Kind() == reflect.Ptr → 是否为指针
  3. 解引用指针t = t.Elem() → 获取指针指向的实际类型
  4. 获取类型名称t.Name() → 类型的字符串名称

关键点:

  • Elem() 用于解引用指针,获取其指向的类型
  • Name() 返回类型的名称,对于命名类型有效
  • 对于指针类型,需要解引用后才能获取实际类型的名称
  • 匿名类型和基本类型处理需要特别注意