Mysql根据内容查找在哪个表(Go版本)

Mysql根据内容查找在哪个表(Go版本)

前言

哈喽,大家好,我是星期八。

事情是这样婶的。

上次我们通过Python语言完成了Mysql根据内容查找在哪个表这个需求。

传送门:Mysql根据内容查找在哪个表(python版本)

但是都知道啊。Python是不太方便打包的。虽然可以。但是毕竟不是那么方便。

所以,思来想去,决定使用Go语言重构这个需求,并且打包成win64win32exe

项目说明

本项目已经上传gitee

地址:mysql_for_table

在这里插入图片描述

下载下来可以发现是有mysql根据内容查询在哪个表这个文件夹的!

里面放的就是打包好的exe,可以直接使用!

在这里插入图片描述

由于小生不才,并没有学会Go GUI相关的知识,所以只能采用读取配置文件的方式进行一些设置!

打开my.ini文件,配置连接数据库相关信息要模糊搜索的内容,修改完记得保存!

在这里插入图片描述

然后,直接双击就好了,32位就双击32位的,64位的双击32和64都行!

在这里插入图片描述

这不,就拿到了数据,还匹配到了哪个字段!

代码解读

全局变量和导入包

import (
	"database/sql"
	"errors"
	"fmt"
	"github.com/go-ini/ini"
	_ "github.com/go-sql-driver/mysql"
	termbox "github.com/nsf/termbox-go"
	"time"
)

//全局变量
var (
	db        *sql.DB
	ip        string
	port      string
	username  string
	password  string
	database  string
	wait_time int
	content   string
)

读取ini文件,赋值给全局变量

读取ini文件这里用到的是github.com/go-ini/ini

安装命令

go get gopkg.in/ini.v1
func initIni() error {
	cfg, err := ini.Load("my.ini")
	if err != nil {
		return errors.New("ini文件读取失败")
	}
	ip = cfg.Section("mysql").Key("ip").String()
	port = cfg.Section("mysql").Key("port").String()
	username = cfg.Section("mysql").Key("username").String()
	password = cfg.Section("mysql").Key("password").String()
	database = cfg.Section("mysql").Key("database").String()
	content = cfg.Section("mysql").Key("content").String()
	wait_time, err = cfg.Section("mysql").Key("wait_time").Int()
	if err != nil {
		return errors.New("wait_time参数不是整数")
	}
	return nil
}

初始化Mysql连接

func initDB() (err error) {
	var dsn = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", username, password, ip, port, database)
	//Open只会验证dsb的格式是否正确,不会验证是否连接成功,同理,密码是否正确也不知道
	db, err = sql.Open("mysql", dsn)
	if err != nil {
		return errors.New("格式错误")
	}
	// 此时尝试连接数据库,会判断用户,密码,ip地址,端口是否正确
	err = db.Ping()
	if err != nil {
		return errors.New("配置错误")
	}
	return nil
}

根据数据库获取当前数据库下所有表

type Table struct {
	//表名
	TableName string
}

// 根据数据库获取当前数据库下所有表
func DatabaseToTables() ([]Table, error) {
	var sqlStr = "show TABLES;"
	rows, err := db.Query(sqlStr)
	if err != nil {
		return nil, errors.New("查询失败")
	}
	defer rows.Close()
	var tables = make([]Table, 0, 100)
	for rows.Next() {
		var table Table
		err = rows.Scan(&table.TableName)
		if err != nil {
			return nil, errors.New("绑定数据失败")
		}
		tables = append(tables, table)
	}
	return tables, nil
}

根据表名获取当前表所有字段

type Field struct {
	//列名
	ColumnName string
}

// 根据表名获取当前表所有字段
func TableToFields(table string) ([]Field, error) {
	var sqlStr = "select COLUMN_NAME from information_schema.COLUMNS where table_name = '%s';"
	sqlStr = fmt.Sprintf(sqlStr, table)
	rows, err := db.Query(sqlStr)
	if err != nil {
		return nil, errors.New("查询失败")
	}
	defer rows.Close()
	var fields = make([]Field, 0, 100)
	for rows.Next() {
		var field Field
		err = rows.Scan(&field.ColumnName)
		if err != nil {
			return nil, errors.New("绑定数据失败")
		}
		fields = append(fields, field)
	}
	return fields, nil
}

根据字段一一查询

func FieldSelect(table, field, content string) (map[string]string, error) {
	//fmt.Println(table, field, content)
	var sqlStr = "SELECT * from %s where %s like '%%%s%%';"
	sqlStr = fmt.Sprintf(sqlStr, table, field, content)
	rows, err := db.Query(sqlStr)
	if err != nil {
		return nil, errors.New("sql查询失败")
	}
	//函数结束释放链接
	defer rows.Close()
	//sql转map
	result, err := ScanRow(rows)
	if err != nil {
		return nil, err
	}
	return result, nil
}

//获取单个
func ScanRow(rows *sql.Rows) (map[string]string, error) {
	//读出查询出的列字段名
	cols, _ := rows.Columns()
	//values是每个列的值,这里获取到byte里
	values := make([][]byte, len(cols))
	//query.Scan的参数,因为每次查询出来的列是不定长的,用len(cols)定住当次查询的长度
	scans := make([]interface{}, len(cols))
	//让每一行数据都填充到[][]byte里面,狸猫换太子
	for i := range values {
		scans[i] = &values[i]
	}
	//获取单行必须Next()
	rows.Next()
	//传指针进去,但是不通过指针能获取值
	err := rows.Scan(scans...)
	if err != nil {
		return nil, errors.New("Scan失败")
	}
	row := make(map[string]string)
	for k, v := range values {
		//cols[k]为字段名
		key := cols[k]
		row[key] = string(v)
	}
	return row, nil
}

暂停等待,不让cmd直接结束

func pause() {
	fmt.Println("请按任意键继续...")
Loop:
	for {
		switch ev := termbox.PollEvent(); ev.Type {
		case termbox.EventKey:
			break Loop
		}
	}
}

main(主要逻辑)

func main() {
	//初始化ini
	err := initIni()
	if err != nil {
		fmt.Println("错误:", err)
		pause()
		return
	}
	//初始化mysql
	err = initDB()
	if err != nil {
		fmt.Println("错误:", err)
		pause()
		return
	}
	//开始时间
	begin_time := time.Now()
	// begin:主要逻辑,三层for循环
	//根据数据库获取当前数据库下所有表
	tables, err := DatabaseToTables()
	if err != nil {
		fmt.Println("错误:", err)
		pause()
		return
	}
	for _, table := range tables {
		fields, err := TableToFields(table.TableName)
		if err != nil {
			fmt.Println("错误:", err)
			pause()
			return
		}
		for _, field := range fields {
			_, err := FieldSelect(table.TableName, field.ColumnName, content)
			//err != nil表示查询失败,继续下次查询
			if err != nil {
				continue
			}
			//fmt.Println(row)
			fmt.Printf("表名:%s,列名:%s\n", table.TableName, field.ColumnName)
			//睡眠指定时间
			time.Sleep(time.Millisecond * time.Duration(wait_time))
		}
	}
	elapsed_time := time.Now().Sub(begin_time)
	fmt.Println("运行时间:", elapsed_time)
	//任意键结束
	pause()
	//end:主要逻辑
}

总结

本次是上次Python脚本的翻译版,但是在此基础之上,让程序变的更通用,直接是exe

源码在这,如果可以,还可以打包成Mac版,Linux版,只要你愿意,咋样都行!

相比之下,我现在开发项目更倾向Go!

如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

乾坤未定,你我皆是黑马。

我是码农星期八,如果觉得还不错,记得动手点赞一下哈。

感谢你的观看。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值