feat(database): 新增命令行参数解析、空值检查和数据库配置管理功能

- 实现了 command 包用于控制台参数和选项解析
- 添加了 empty 包提供变量空值/零值检查功能
- 集成了 Viper 库进行配置文件管理和环境变量支持
- 提供了数据库配置初始化和默认值设置功能
- 实现了配置值获取、设置和结构化解析方法
- 添加了服务器、数据库和JWT配置的便捷获取方法
- 实现了完整的数据库接口定义和事务管理功能
This commit is contained in:
maguodong
2026-04-08 09:33:59 +08:00
parent 6dcd564206
commit af0a8f4043
132 changed files with 14331 additions and 10719 deletions
+8
View File
@@ -0,0 +1,8 @@
// 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 utils provides some utility functions for internal usage.
package utils
+26
View File
@@ -0,0 +1,26 @@
// 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 utils
import "reflect"
// IsArray checks whether given value is array/slice.
// Note that it uses reflect internally implementing this feature.
func IsArray(value any) bool {
rv := reflect.ValueOf(value)
kind := rv.Kind()
if kind == reflect.Pointer {
rv = rv.Elem()
kind = rv.Kind()
}
switch kind {
case reflect.Array, reflect.Slice:
return true
default:
return false
}
}
+38
View File
@@ -0,0 +1,38 @@
// 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 utils
import "git.magicany.cc/black1552/gin-base/database/command"
const (
// Debug key for checking if in debug mode.
commandEnvKeyForDebugKey = "gf.debug"
)
// isDebugEnabled marks whether GoFrame debug mode is enabled.
var isDebugEnabled = false
func init() {
// Debugging configured.
value := command.GetOptWithEnv(commandEnvKeyForDebugKey)
if value == "" || value == "0" || value == "false" {
isDebugEnabled = false
} else {
isDebugEnabled = true
}
}
// IsDebugEnabled checks and returns whether debug mode is enabled.
// The debug mode is enabled when command argument "gf.debug" or environment "GF_DEBUG" is passed.
func IsDebugEnabled() bool {
return isDebugEnabled
}
// SetDebugEnabled enables/disables the internal debug info.
func SetDebugEnabled(enabled bool) {
isDebugEnabled = enabled
}
+48
View File
@@ -0,0 +1,48 @@
// 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 utils
import (
"io"
)
// ReadCloser implements the io.ReadCloser interface
// which is used for reading request body content multiple times.
//
// Note that it cannot be closed.
type ReadCloser struct {
index int // Current read position.
content []byte // Content.
repeatable bool // Mark the content can be repeatable read.
}
// NewReadCloser creates and returns a RepeatReadCloser object.
func NewReadCloser(content []byte, repeatable bool) io.ReadCloser {
return &ReadCloser{
content: content,
repeatable: repeatable,
}
}
// Read implements the io.ReadCloser interface.
func (b *ReadCloser) Read(p []byte) (n int, err error) {
// Make it repeatable reading.
if b.index >= len(b.content) && b.repeatable {
b.index = 0
}
n = copy(p, b.content[b.index:])
b.index += n
if b.index >= len(b.content) {
return n, io.EOF
}
return n, nil
}
// Close implements the io.ReadCloser interface.
func (b *ReadCloser) Close() error {
return nil
}
+102
View File
@@ -0,0 +1,102 @@
// 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 utils
import (
"reflect"
"git.magicany.cc/black1552/gin-base/database/empty"
)
// IsNil checks whether `value` is nil, especially for any type value.
func IsNil(value any) bool {
return empty.IsNil(value)
}
// IsEmpty checks whether `value` is empty.
func IsEmpty(value any) bool {
return empty.IsEmpty(value)
}
// IsInt checks whether `value` is type of int.
func IsInt(value any) bool {
switch value.(type) {
case int, *int, int8, *int8, int16, *int16, int32, *int32, int64, *int64:
return true
}
return false
}
// IsUint checks whether `value` is type of uint.
func IsUint(value any) bool {
switch value.(type) {
case uint, *uint, uint8, *uint8, uint16, *uint16, uint32, *uint32, uint64, *uint64:
return true
}
return false
}
// IsFloat checks whether `value` is type of float.
func IsFloat(value any) bool {
switch value.(type) {
case float32, *float32, float64, *float64:
return true
}
return false
}
// IsSlice checks whether `value` is type of slice.
func IsSlice(value any) bool {
var (
reflectValue = reflect.ValueOf(value)
reflectKind = reflectValue.Kind()
)
for reflectKind == reflect.Pointer {
reflectValue = reflectValue.Elem()
reflectKind = reflectValue.Kind()
}
switch reflectKind {
case reflect.Slice, reflect.Array:
return true
}
return false
}
// IsMap checks whether `value` is type of map.
func IsMap(value any) bool {
var (
reflectValue = reflect.ValueOf(value)
reflectKind = reflectValue.Kind()
)
for reflectKind == reflect.Pointer {
reflectValue = reflectValue.Elem()
reflectKind = reflectValue.Kind()
}
switch reflectKind {
case reflect.Map:
return true
}
return false
}
// IsStruct checks whether `value` is type of struct.
func IsStruct(value any) bool {
reflectType := reflect.TypeOf(value)
if reflectType == nil {
return false
}
reflectKind := reflectType.Kind()
for reflectKind == reflect.Pointer {
reflectType = reflectType.Elem()
reflectKind = reflectType.Kind()
}
switch reflectKind {
case reflect.Struct:
return true
}
return false
}
+37
View File
@@ -0,0 +1,37 @@
// 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 utils
import "fmt"
// ListToMapByKey converts `list` to a map[string]any of which key is specified by `key`.
// Note that the item value may be type of slice.
func ListToMapByKey(list []map[string]any, key string) map[string]any {
var (
s = ""
m = make(map[string]any)
tempMap = make(map[string][]any)
hasMultiValues bool
)
for _, item := range list {
if k, ok := item[key]; ok {
s = fmt.Sprintf(`%v`, k)
tempMap[s] = append(tempMap[s], item)
if len(tempMap[s]) > 1 {
hasMultiValues = true
}
}
}
for k, v := range tempMap {
if hasMultiValues {
m[k] = v
} else {
m[k] = v[0]
}
}
return m
}
+37
View File
@@ -0,0 +1,37 @@
// 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 utils
// MapPossibleItemByKey tries to find the possible key-value pair for given key ignoring cases and symbols.
//
// Note that this function might be of low performance.
func MapPossibleItemByKey(data map[string]any, key string) (foundKey string, foundValue any) {
if len(data) == 0 {
return
}
if v, ok := data[key]; ok {
return key, v
}
// Loop checking.
for k, v := range data {
if EqualFoldWithoutChars(k, key) {
return k, v
}
}
return "", nil
}
// MapContainsPossibleKey checks if the given `key` is contained in given map `data`.
// It checks the key ignoring cases and symbols.
//
// Note that this function might be of low performance.
func MapContainsPossibleKey(data map[string]any, key string) bool {
if k, _ := MapPossibleItemByKey(data, key); k != "" {
return true
}
return false
}
+26
View File
@@ -0,0 +1,26 @@
// 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 utils
import (
"reflect"
)
// CanCallIsNil Can reflect.Value call reflect.Value.IsNil.
// It can avoid reflect.Value.IsNil panics.
func CanCallIsNil(v any) bool {
rv, ok := v.(reflect.Value)
if !ok {
return false
}
switch rv.Kind() {
case reflect.Interface, reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.Slice, reflect.UnsafePointer:
return true
default:
return false
}
}
+180
View File
@@ -0,0 +1,180 @@
// 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 utils
import (
"bytes"
"strings"
"unicode"
)
// DefaultTrimChars are the characters which are stripped by Trim* functions in default.
var DefaultTrimChars = string([]byte{
'\t', // Tab.
'\v', // Vertical tab.
'\n', // New line (line feed).
'\r', // Carriage return.
'\f', // New page.
' ', // Ordinary space.
0x00, // NUL-byte.
0x85, // Delete.
0xA0, // Non-breaking space.
})
// IsLetterUpper checks whether the given byte b is in upper case.
func IsLetterUpper(b byte) bool {
if b >= byte('A') && b <= byte('Z') {
return true
}
return false
}
// IsLetterLower checks whether the given byte b is in lower case.
func IsLetterLower(b byte) bool {
if b >= byte('a') && b <= byte('z') {
return true
}
return false
}
// IsLetter checks whether the given byte b is a letter.
func IsLetter(b byte) bool {
return IsLetterUpper(b) || IsLetterLower(b)
}
// IsNumeric checks whether the given string s is numeric.
// Note that float string like "123.456" is also numeric.
func IsNumeric(s string) bool {
var (
dotCount = 0
length = len(s)
)
if length == 0 {
return false
}
for i := 0; i < length; i++ {
if (s[i] == '-' || s[i] == '+') && i == 0 {
if length == 1 {
return false
}
continue
}
if s[i] == '.' {
dotCount++
if i > 0 && i < length-1 && s[i-1] >= '0' && s[i-1] <= '9' {
continue
} else {
return false
}
}
if s[i] < '0' || s[i] > '9' {
return false
}
}
return dotCount <= 1
}
// UcFirst returns a copy of the string s with the first letter mapped to its upper case.
func UcFirst(s string) string {
if len(s) == 0 {
return s
}
if IsLetterLower(s[0]) {
return string(s[0]-32) + s[1:]
}
return s
}
// ReplaceByMap returns a copy of `origin`,
// which is replaced by a map in unordered way, case-sensitively.
func ReplaceByMap(origin string, replaces map[string]string) string {
for k, v := range replaces {
origin = strings.ReplaceAll(origin, k, v)
}
return origin
}
// RemoveSymbols removes all symbols from string and lefts only numbers and letters.
func RemoveSymbols(s string) string {
b := make([]rune, 0, len(s))
for _, c := range s {
if c > 127 {
b = append(b, c)
} else if (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') {
b = append(b, c)
}
}
return string(b)
}
// EqualFoldWithoutChars checks string `s1` and `s2` equal case-insensitively,
// with/without chars '-'/'_'/'.'/' '.
func EqualFoldWithoutChars(s1, s2 string) bool {
return strings.EqualFold(RemoveSymbols(s1), RemoveSymbols(s2))
}
// SplitAndTrim splits string `str` by a string `delimiter` to an array,
// and calls Trim to every element of this array. It ignores the elements
// which are empty after Trim.
func SplitAndTrim(str, delimiter string, characterMask ...string) []string {
array := make([]string, 0)
for _, v := range strings.Split(str, delimiter) {
v = Trim(v, characterMask...)
if v != "" {
array = append(array, v)
}
}
return array
}
// Trim strips whitespace (or other characters) from the beginning and end of a string.
// The optional parameter `characterMask` specifies the additional stripped characters.
func Trim(str string, characterMask ...string) string {
trimChars := DefaultTrimChars
if len(characterMask) > 0 {
trimChars += characterMask[0]
}
return strings.Trim(str, trimChars)
}
// FormatCmdKey formats string `s` as command key using uniformed format.
func FormatCmdKey(s string) string {
return strings.ToLower(strings.ReplaceAll(s, "_", "."))
}
// FormatEnvKey formats string `s` as environment key using uniformed format.
func FormatEnvKey(s string) string {
return strings.ToUpper(strings.ReplaceAll(s, ".", "_"))
}
// StripSlashes un-quotes a quoted string by AddSlashes.
func StripSlashes(str string) string {
var buf bytes.Buffer
l, skip := len(str), false
for i, char := range str {
if skip {
skip = false
} else if char == '\\' {
if i+1 < l && str[i+1] == '\\' {
skip = true
}
continue
}
buf.WriteRune(char)
}
return buf.String()
}
// IsASCII checks whether given string is ASCII characters.
func IsASCII(s string) bool {
for i := 0; i < len(s); i++ {
if s[i] > unicode.MaxASCII {
return false
}
}
return true
}