mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
This pull request standardizes the use of the Go 1.18+ `any` type alias
instead of `interface{}` throughout the codebase. The change improves
code readability and aligns with modern Go best practices. The update
touches many files, including core data structures, code generation
templates, logging utilities, and test data, ensuring consistency across
all usages.
**Type alias migration to `any`:**
* Replaced all instances of `interface{}` with `any` in core data
structures such as `garray` and in generated model structs (e.g.,
`TableUser`, `User1`, `User2`) to modernize type usage.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[3]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[4]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[5]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[6]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
* Updated function signatures, method parameters, and return types from
`interface{}` to `any` in various parts of the codebase, including code
generation, service logic, and logging utilities (e.g., `mlog`).
[[1]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[2]](diffhunk://#diff-2b1953fb78cf3593d8c2c7d911e95b65fd0b847c30ed0b4d167d16fe6d781235L54-R74)
[[3]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[4]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
[[5]](diffhunk://#diff-c5d51d56f487779a2b6207c7ad26c7a20bbadcc846ce094fe60ab4cabff58c51L107-R107)
[[6]](diffhunk://#diff-f96e6a9fdb416eb1804ceaba1fe0ac637bff22c43837f8bb849c2366ce72d4a1L116-R121)
[[7]](diffhunk://#diff-f94c83a1b08ae060d9346f4a6031fc4a7b9a0b894e02d9afaa09018b6598eac0L112-R112)
[[8]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L36-R36)
[[9]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L74-R74)
[[10]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L96-R96)
**Generated code and templates:**
* Adjusted generated files and code generation templates to output `any`
instead of `interface{}` for relevant struct fields and function
signatures, ensuring that new code generation aligns with the updated
convention.
[[1]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[2]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[3]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[4]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[5]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
[[6]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[7]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[8]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
**Container and utility updates:**
* Refactored the `garray` container implementation and related
constructors/methods to use `[]any` instead of `[]interface{}`, along
with corresponding function signatures.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L52-R52)
[[3]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L62-R62)
[[4]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L73-R86)
[[5]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L96-R97)
[[6]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L107-R114)
[[7]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L124-R124)
[[8]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L135-R143)
[[9]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L167-R167)
These changes collectively modernize the codebase and prepare it for
future Go developments by using the idiomatic `any` type.
276 lines
8.0 KiB
Go
276 lines
8.0 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package gdb
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/gogf/gf/v2/container/gset"
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
)
|
|
|
|
// Fields appends `fieldNamesOrMapStruct` to the operation fields of the model, multiple fields joined using char ','.
|
|
// The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct.
|
|
//
|
|
// Example:
|
|
// Fields("id", "name", "age")
|
|
// Fields([]string{"id", "name", "age"})
|
|
// Fields(map[string]any{"id":1, "name":"john", "age":18})
|
|
// Fields(User{Id: 1, Name: "john", Age: 18}).
|
|
func (m *Model) Fields(fieldNamesOrMapStruct ...any) *Model {
|
|
length := len(fieldNamesOrMapStruct)
|
|
if length == 0 {
|
|
return m
|
|
}
|
|
fields := m.filterFieldsFrom(m.tablesInit, fieldNamesOrMapStruct...)
|
|
if len(fields) == 0 {
|
|
return m
|
|
}
|
|
model := m.getModel()
|
|
return model.appendToFields(fields...)
|
|
}
|
|
|
|
// FieldsPrefix performs as function Fields but add extra prefix for each field.
|
|
func (m *Model) FieldsPrefix(prefixOrAlias string, fieldNamesOrMapStruct ...any) *Model {
|
|
fields := m.filterFieldsFrom(
|
|
m.getTableNameByPrefixOrAlias(prefixOrAlias),
|
|
fieldNamesOrMapStruct...,
|
|
)
|
|
if len(fields) == 0 {
|
|
return m
|
|
}
|
|
for i, field := range fields {
|
|
fields[i] = prefixOrAlias + "." + gconv.String(field)
|
|
}
|
|
model := m.getModel()
|
|
return model.appendToFields(fields...)
|
|
}
|
|
|
|
// FieldsEx appends `fieldNamesOrMapStruct` to the excluded operation fields of the model,
|
|
// multiple fields joined using char ','.
|
|
// Note that this function supports only single table operations.
|
|
// The parameter `fieldNamesOrMapStruct` can be type of string/map/*map/struct/*struct.
|
|
//
|
|
// Example:
|
|
// FieldsEx("id", "name", "age")
|
|
// FieldsEx([]string{"id", "name", "age"})
|
|
// FieldsEx(map[string]any{"id":1, "name":"john", "age":18})
|
|
// FieldsEx(User{Id: 1, Name: "john", Age: 18}).
|
|
func (m *Model) FieldsEx(fieldNamesOrMapStruct ...any) *Model {
|
|
return m.doFieldsEx(m.tablesInit, fieldNamesOrMapStruct...)
|
|
}
|
|
|
|
func (m *Model) doFieldsEx(table string, fieldNamesOrMapStruct ...any) *Model {
|
|
length := len(fieldNamesOrMapStruct)
|
|
if length == 0 {
|
|
return m
|
|
}
|
|
fields := m.filterFieldsFrom(table, fieldNamesOrMapStruct...)
|
|
if len(fields) == 0 {
|
|
return m
|
|
}
|
|
model := m.getModel()
|
|
model.fieldsEx = append(model.fieldsEx, fields...)
|
|
return model
|
|
}
|
|
|
|
// FieldsExPrefix performs as function FieldsEx but add extra prefix for each field.
|
|
func (m *Model) FieldsExPrefix(prefixOrAlias string, fieldNamesOrMapStruct ...any) *Model {
|
|
model := m.doFieldsEx(
|
|
m.getTableNameByPrefixOrAlias(prefixOrAlias),
|
|
fieldNamesOrMapStruct...,
|
|
)
|
|
for i, field := range model.fieldsEx {
|
|
model.fieldsEx[i] = prefixOrAlias + "." + gconv.String(field)
|
|
}
|
|
return model
|
|
}
|
|
|
|
// FieldCount formats and appends commonly used field `COUNT(column)` to the select fields of model.
|
|
func (m *Model) FieldCount(column string, as ...string) *Model {
|
|
asStr := ""
|
|
if len(as) > 0 && as[0] != "" {
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
}
|
|
model := m.getModel()
|
|
return model.appendToFields(
|
|
fmt.Sprintf(`COUNT(%s)%s`, m.QuoteWord(column), asStr),
|
|
)
|
|
}
|
|
|
|
// FieldSum formats and appends commonly used field `SUM(column)` to the select fields of model.
|
|
func (m *Model) FieldSum(column string, as ...string) *Model {
|
|
asStr := ""
|
|
if len(as) > 0 && as[0] != "" {
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
}
|
|
model := m.getModel()
|
|
return model.appendToFields(
|
|
fmt.Sprintf(`SUM(%s)%s`, m.QuoteWord(column), asStr),
|
|
)
|
|
}
|
|
|
|
// FieldMin formats and appends commonly used field `MIN(column)` to the select fields of model.
|
|
func (m *Model) FieldMin(column string, as ...string) *Model {
|
|
asStr := ""
|
|
if len(as) > 0 && as[0] != "" {
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
}
|
|
model := m.getModel()
|
|
return model.appendToFields(
|
|
fmt.Sprintf(`MIN(%s)%s`, m.QuoteWord(column), asStr),
|
|
)
|
|
}
|
|
|
|
// FieldMax formats and appends commonly used field `MAX(column)` to the select fields of model.
|
|
func (m *Model) FieldMax(column string, as ...string) *Model {
|
|
asStr := ""
|
|
if len(as) > 0 && as[0] != "" {
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
}
|
|
model := m.getModel()
|
|
return model.appendToFields(
|
|
fmt.Sprintf(`MAX(%s)%s`, m.QuoteWord(column), asStr),
|
|
)
|
|
}
|
|
|
|
// FieldAvg formats and appends commonly used field `AVG(column)` to the select fields of model.
|
|
func (m *Model) FieldAvg(column string, as ...string) *Model {
|
|
asStr := ""
|
|
if len(as) > 0 && as[0] != "" {
|
|
asStr = fmt.Sprintf(` AS %s`, m.db.GetCore().QuoteWord(as[0]))
|
|
}
|
|
model := m.getModel()
|
|
return model.appendToFields(
|
|
fmt.Sprintf(`AVG(%s)%s`, m.QuoteWord(column), asStr),
|
|
)
|
|
}
|
|
|
|
// GetFieldsStr retrieves and returns all fields from the table, joined with char ','.
|
|
// The optional parameter `prefix` specifies the prefix for each field, eg: GetFieldsStr("u.").
|
|
func (m *Model) GetFieldsStr(prefix ...string) string {
|
|
prefixStr := ""
|
|
if len(prefix) > 0 {
|
|
prefixStr = prefix[0]
|
|
}
|
|
tableFields, err := m.TableFields(m.tablesInit)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if len(tableFields) == 0 {
|
|
panic(fmt.Sprintf(`empty table fields for table "%s"`, m.tables))
|
|
}
|
|
fieldsArray := make([]string, len(tableFields))
|
|
for k, v := range tableFields {
|
|
fieldsArray[v.Index] = k
|
|
}
|
|
newFields := ""
|
|
for _, k := range fieldsArray {
|
|
if len(newFields) > 0 {
|
|
newFields += ","
|
|
}
|
|
newFields += prefixStr + k
|
|
}
|
|
newFields = m.db.GetCore().QuoteString(newFields)
|
|
return newFields
|
|
}
|
|
|
|
// GetFieldsExStr retrieves and returns fields which are not in parameter `fields` from the table,
|
|
// joined with char ','.
|
|
// The parameter `fields` specifies the fields that are excluded.
|
|
// The optional parameter `prefix` specifies the prefix for each field, eg: FieldsExStr("id", "u.").
|
|
func (m *Model) GetFieldsExStr(fields string, prefix ...string) (string, error) {
|
|
prefixStr := ""
|
|
if len(prefix) > 0 {
|
|
prefixStr = prefix[0]
|
|
}
|
|
tableFields, err := m.TableFields(m.tablesInit)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(tableFields) == 0 {
|
|
return "", gerror.Newf(`empty table fields for table "%s"`, m.tables)
|
|
}
|
|
fieldsExSet := gset.NewStrSetFrom(gstr.SplitAndTrim(fields, ","))
|
|
fieldsArray := make([]string, len(tableFields))
|
|
for k, v := range tableFields {
|
|
fieldsArray[v.Index] = k
|
|
}
|
|
newFields := ""
|
|
for _, k := range fieldsArray {
|
|
if fieldsExSet.Contains(k) {
|
|
continue
|
|
}
|
|
if len(newFields) > 0 {
|
|
newFields += ","
|
|
}
|
|
newFields += prefixStr + k
|
|
}
|
|
newFields = m.db.GetCore().QuoteString(newFields)
|
|
return newFields, nil
|
|
}
|
|
|
|
// HasField determine whether the field exists in the table.
|
|
func (m *Model) HasField(field string) (bool, error) {
|
|
return m.db.GetCore().HasField(m.GetCtx(), m.tablesInit, field)
|
|
}
|
|
|
|
// getFieldsFrom retrieves, filters and returns fields name from table `table`.
|
|
func (m *Model) filterFieldsFrom(table string, fieldNamesOrMapStruct ...any) []any {
|
|
length := len(fieldNamesOrMapStruct)
|
|
if length == 0 {
|
|
return nil
|
|
}
|
|
switch {
|
|
// String slice.
|
|
case length >= 2:
|
|
return m.mappingAndFilterToTableFields(
|
|
table, fieldNamesOrMapStruct, true,
|
|
)
|
|
|
|
// It needs type asserting.
|
|
case length == 1:
|
|
structOrMap := fieldNamesOrMapStruct[0]
|
|
switch r := structOrMap.(type) {
|
|
case string:
|
|
return m.mappingAndFilterToTableFields(table, []any{r}, false)
|
|
|
|
case []string:
|
|
return m.mappingAndFilterToTableFields(table, gconv.Interfaces(r), true)
|
|
|
|
case Raw, *Raw:
|
|
return []any{structOrMap}
|
|
|
|
default:
|
|
return m.mappingAndFilterToTableFields(table, getFieldsFromStructOrMap(structOrMap), true)
|
|
}
|
|
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (m *Model) appendToFields(fields ...any) *Model {
|
|
if len(fields) == 0 {
|
|
return m
|
|
}
|
|
model := m.getModel()
|
|
model.fields = append(model.fields, fields...)
|
|
return model
|
|
}
|
|
|
|
func (m *Model) isFieldInFieldsEx(field string) bool {
|
|
for _, v := range m.fieldsEx {
|
|
if v == field {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|