go gorm select * 优化

很多时候sql查询都不允许select * 出现要求指定列名,如果你是用gormv2 ,恭喜你可以使用QueryFields属性,如果是gormv1版本怎么样,难道要升级gormV2吗,这里提供种反射的实现,可能不是最优解,但只是一个方案。

首先mysq建一个表

CREATE TABLE `test` (
  `id` BIGINT(20) NOT NULL,
  `name` VARCHAR(5) DEFAULT NULL,
  `age` INT(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 

go的代码如下:

package main

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"reflect"
	"strings"

	_ "github.com/go-sql-driver/mysql"
	"gorm.io/gorm"
)

func main() {
	dns := "root:root@tcp(192.168.100.30:3306)/demo?charset=utf8&parseTime=True&loc=Local"
	config := &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true,
		},
		//QueryFields: true,
		Logger: logger.Default.LogMode(logger.Info),
	}

	db, err := gorm.Open(mysql.Open(dns), config)
	if err != nil {
		fmt.Println(fmt.Sprintf("Open err:%v", err))
	}

	var ret []*Test
	//一般查询
	fmt.Println("一般查询")
	err = db.Table("test").Where("id>1").Find(&ret).Debug().Error
	if err != nil {
		fmt.Println(fmt.Sprintf("select err:%v", err))
	}

	//通过反射指定列
	fmt.Println("通过反射指定列")
	err = db.Table("test").Where("id>1").Select(GetAllFields(new(Test))).Find(&ret).Debug().Error
	if err != nil {
		fmt.Println(fmt.Sprintf("select err:%v", err))
	}

	//通过QueryFields 指定列
	fmt.Println("通过QueryFields 指定列")
	tx := db.Table("test")
	tx.QueryFields = true
	err = tx.Where("id>1").Find(&ret).Debug().Error
	if err != nil {
		fmt.Println(fmt.Sprintf("select err:%v", err))
	}
}

type Test struct {
	ID   int64  `gorm:"type:bigint(20);column:id;primary_key"`
	Name string `gorm:"type:varchar(5);column:name"`
	Age  int    `gorm:"type:int(11);column:age"`
}

func GetAllFields(info interface{}) string {
	tagName := strings.ToUpper("column")
	var arr []string
	el := reflect.TypeOf(info).Elem()
	for i := 0; i < el.NumField(); i++ {
		structTag := el.Field(i).Tag
		tags := parseTagSetting(structTag)
		if columnName, ok := tags[tagName]; ok && columnName != "-" {
			arr = append(arr, columnName)
		}
	}
	sqlFields := "`" + strings.Join(arr, "`,`") + "`"
	return sqlFields
}

func parseTagSetting(tags reflect.StructTag) map[string]string {
	setting := map[string]string{}
	for _, str := range []string{tags.Get("sql"), tags.Get("gorm")} {
		if str == "" {
			continue
		}
		tags := strings.Split(str, ";")
		for _, value := range tags {
			v := strings.Split(value, ":")
			k := strings.TrimSpace(strings.ToUpper(v[0]))
			if len(v) >= 2 {
				setting[k] = strings.Join(v[1:], ":")
			} else {
				setting[k] = k
			}
		}
	}
	return setting
}

运行结果:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值