代码拉取完成,页面将自动刷新
package main
import (
"fmt"
"io"
"os"
"os/exec"
"slices"
"strings"
"sync"
"github.com/spf13/cobra"
)
type GoType struct {
Name string `json:"name"`
PkgPath string `json:"pkgPath"`
}
type TableField struct {
Name string `json:"name"`
ColumnName string `json:"columnName"`
DbType string `json:"dbType"`
GoType *GoType `json:"goType"`
Comment string `json:"comment"`
DefaultValue bool `json:"defaultValue"`
PrimaryKey bool `json:"primaryKey"`
AutoInc bool `json:"autoInc"`
Unique bool `json:"unique"`
Nullable bool `json:"nullable"`
OnUpdate bool `json:"onUpdate"`
SoftDelete bool `json:"softDelete"`
BaseModel bool `json:"baseModel"`
}
type TableDesc struct {
Name string `json:"name"`
TableName string `json:"tableName"`
Comment string `json:"comment"`
BaseType *GoType `json:"baseType"`
Fields []*TableField `json:"fields"`
}
type CommonOptions struct {
writeGo bool
force bool
gofmt bool
}
func (opts *CommonOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().BoolVarP(&opts.writeGo, "write", "w", false, "write to {table name}.go")
cmd.Flags().BoolVarP(&opts.force, "force", "f", false, "force write")
cmd.Flags().BoolVarP(&opts.gofmt, "gofmt", "F", false, "run gofmt for {table name}.go")
}
func runGofmt(gofile string) error {
cmdArgs := slices.Clone(goFmtCmd)
for i, a := range cmdArgs {
if a == "{}" {
cmdArgs[i] = gofile
}
}
gofmt := exec.Command(cmdArgs[0], cmdArgs[1:]...)
gofmt.Stderr = os.Stderr
return gofmt.Run()
}
func writeOutput(outputFile string, templateName string, doc any, opts *CommonOptions) error {
err := func() error {
var w io.Writer
if opts.writeGo {
fi, _ := os.Stat(outputFile)
if fi != nil && !opts.force {
fatalf("file %s existed\n", outputFile)
}
f, err := os.Create(outputFile)
if err != nil {
return err
}
defer f.Close()
w = f
} else {
w = os.Stdout
}
return rootTemplate.ExecuteTemplate(w, templateName, doc)
}()
if err != nil {
return err
}
if opts.writeGo && opts.gofmt {
_ = runGofmt(outputFile)
}
return nil
}
var (
columnTypes map[string]string
mysqlTypeMap = map[string]string{
"int": "int64",
"integer": "int64",
"tinyint": "int64",
"smallint": "int64",
"mediumint": "int64",
"bigint": "int64",
"int unsigned": "uint64",
"integer unsigned": "uint64",
"tinyint unsigned": "uint64",
"smallint unsigned": "uint64",
"mediumint unsigned": "uint64",
"bigint unsigned": "uint64",
"bit": "byte",
"bool": "bool",
"enum": "string",
"set": "string",
"varchar": "string",
"char": "string",
"tinytext": "string",
"mediumtext": "string",
"text": "string",
"longtext": "string",
"blob": "[]byte",
"tinyblob": "[]byte",
"mediumblob": "[]byte",
"longblob": "[]byte",
"date": "time.Time",
"datetime": "time.Time",
"timestamp": "time.Time",
"time": "time.Time",
"float": "float64",
"double": "float64",
"decimal": "float64",
"binary": "[]byte",
"varbinary": "[]byte",
"json": "[]byte",
}
tablePrefixes []string
baseModelType *GoType
baseModelColumns map[string]bool
softDeleteColumn string
softDeleteType *GoType
goFmtCmd = []string{"gofmt", "-w", "{}"}
)
var initCommonConfig = sync.OnceFunc(func() {
commonConfig := getAppConfig().Common
tablePrefixes = commonConfig.TablePrefixes
columnTypes = commonConfig.ColumnTypes
if commonConfig.GoFmt != nil {
goFmtCmd = append([]string{commonConfig.GoFmt.Cmd}, commonConfig.GoFmt.Args...)
}
modelConfig := getAppConfig().Model
if modelConfig.BaseModel != nil && modelConfig.BaseModel.TypeName != "" {
baseModelType = parseGoType(modelConfig.BaseModel.TypeName)
baseModelColumns = make(map[string]bool)
for _, name := range modelConfig.BaseModel.Fields {
baseModelColumns[name] = true
}
}
if modelConfig.SoftDelete != nil {
softDeleteColumn = modelConfig.SoftDelete.ColumnName
softDeleteType = parseGoType(modelConfig.SoftDelete.TypeName)
}
})
func mapSqlTypeToGo(tableName string, column *TableColumn) (string, error) {
goType := columnTypes[tableName+"."+column.columnName]
if goType != "" {
return goType, nil
}
goType = mysqlTypeMap[column.dataType]
if goType == "" {
return "", fmt.Errorf("cannot map sql data type %s", column.dataType)
}
if column.isNullable {
nullable := mysqlTypeMap[column.dataType+"?"]
if nullable != "" {
goType = nullable
} else {
goType = "*" + goType
}
}
return goType, nil
}
func parseGoType(typeExpr string) *GoType {
// {prefix}{pkgPath}/{pkgName}.{typname}
s := strings.TrimLeft(typeExpr, "*[]")
prefix := len(typeExpr) - len(s)
slash := strings.LastIndexByte(s, '/')
quadId := s[slash+1:]
dot := strings.LastIndexByte(quadId, '.')
pkg := ""
if dot >= 0 {
pkg = s[:slash+1+dot]
}
return &GoType{
PkgPath: pkg,
Name: typeExpr[:prefix] + quadId,
}
}
func getTableDesc(database string, tableName string, useBaseModel bool) (*TableDesc, error) {
tableColumns, err := getTableColumns(database, tableName)
if err != nil {
return nil, err
}
if len(tableColumns) == 0 {
return nil, fmt.Errorf("table %q not found", database+"."+tableName)
}
tableComment, err := getTableComment(database, tableName)
if err != nil {
return nil, err
}
structName := camelCase(removePrefix(tablePrefixes, tableName), false)
fields := make([]*TableField, 0, len(tableColumns))
var baseType *GoType
if len(baseModelColumns) > 0 {
baseModelColumnNum := 0
for _, column := range tableColumns {
if baseModelColumns[column.columnName] {
baseModelColumnNum++
}
}
if baseModelColumnNum == len(baseModelColumns) {
baseType = baseModelType
}
}
for _, column := range tableColumns {
if useBaseModel && baseType != nil && baseModelColumns[column.columnName] {
// skip base model fields
continue
}
fieldName := camelCase(column.columnName, false)
var goType *GoType
if column.columnName == softDeleteColumn {
goType = softDeleteType
} else {
goTypeName, err := mapSqlTypeToGo(tableName, column)
if err != nil {
return nil, err
}
goType = parseGoType(goTypeName)
}
fields = append(fields, &TableField{
Name: fieldName,
ColumnName: column.columnName,
DbType: column.dataType,
GoType: goType,
Comment: column.columnComment,
PrimaryKey: column.isPrimaryKey,
DefaultValue: column.columnDefault.Valid || column.hasAutoIncrement,
AutoInc: column.hasAutoIncrement,
Unique: column.isUniqueKey,
Nullable: column.isNullable,
OnUpdate: column.hasOnUpdate,
SoftDelete: column.columnName == softDeleteColumn,
BaseModel: baseType != nil && baseModelColumns[column.columnName],
})
}
if !useBaseModel {
baseType = nil
}
return &TableDesc{
Name: structName,
TableName: tableName,
Comment: tableComment,
Fields: fields,
BaseType: baseType,
}, nil
}
func splitDatabaseTable(tableName string) (string, string, string) {
db, tbl, ok := strings.Cut(tableName, ".")
if !ok {
return getAppConfig().Mysql.Database, tableName, ""
}
return db, tbl, db + "."
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。