reface to openteam
This commit is contained in:
16
internal/utils/convert.go
Normal file
16
internal/utils/convert.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package utils
|
||||
|
||||
import "strings"
|
||||
|
||||
func StringToBool(strSlice []string) []bool {
|
||||
boolSlice := make([]bool, len(strSlice))
|
||||
for i, str := range strSlice {
|
||||
str = strings.ToLower(str)
|
||||
if str == "true" {
|
||||
boolSlice[i] = true
|
||||
} else if str == "false" {
|
||||
boolSlice[i] = false
|
||||
}
|
||||
}
|
||||
return boolSlice
|
||||
}
|
||||
139
internal/utils/map_tools.go
Normal file
139
internal/utils/map_tools.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func MergeJSONObjects(dst, src map[string]interface{}) map[string]interface{} {
|
||||
|
||||
result := make(map[string]interface{})
|
||||
for k, v := range dst {
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
for key, value2 := range src {
|
||||
value1, exists := result[key]
|
||||
|
||||
if exists {
|
||||
map1Val, map1IsMap := value1.(map[string]interface{})
|
||||
map2Val, map2IsMap := value2.(map[string]interface{})
|
||||
|
||||
if map1IsMap && map2IsMap {
|
||||
result[key] = MergeJSONObjects(map1Val, map2Val)
|
||||
} else {
|
||||
// 覆盖第一个map中的值
|
||||
result[key] = value2
|
||||
}
|
||||
} else {
|
||||
// 添加新的键值对
|
||||
result[key] = value2
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func StructToMap(in interface{}) (map[string]interface{}, error) {
|
||||
out := make(map[string]interface{})
|
||||
|
||||
v := reflect.ValueOf(in)
|
||||
// If it's a pointer, dereference it
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
// Check if it's a struct
|
||||
if v.Kind() != reflect.Struct {
|
||||
return nil, fmt.Errorf("StructToMap only accepts structs or pointers to structs; got %T", v.Interface())
|
||||
}
|
||||
|
||||
t := v.Type() // Get the type of the struct
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
// Get the field Value and Type
|
||||
fieldV := v.Field(i)
|
||||
fieldT := t.Field(i)
|
||||
|
||||
// Skip unexported fields
|
||||
if !fieldT.IsExported() {
|
||||
continue
|
||||
}
|
||||
|
||||
// --- Handle JSON Tag ---
|
||||
tag := fieldT.Tag.Get("json")
|
||||
key := fieldT.Name // Default key is the field name
|
||||
omitempty := false
|
||||
|
||||
if tag != "" {
|
||||
parts := strings.Split(tag, ",")
|
||||
tagName := parts[0]
|
||||
|
||||
if tagName == "-" {
|
||||
// Skip fields tagged with "-"
|
||||
continue
|
||||
}
|
||||
if tagName != "" {
|
||||
key = tagName // Use tag name as key
|
||||
}
|
||||
|
||||
// Check for omitempty option
|
||||
for _, part := range parts[1:] {
|
||||
if part == "omitempty" {
|
||||
omitempty = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Handle omitempty ---
|
||||
val := fieldV.Interface()
|
||||
if omitempty && fieldV.IsZero() {
|
||||
continue // Skip zero-value fields if omitempty is set
|
||||
}
|
||||
|
||||
// --- Handle Nested Structs/Pointers to Structs (Recursion) ---
|
||||
// Check for pointer first
|
||||
if fieldV.Kind() == reflect.Ptr {
|
||||
// If pointer is nil and omitempty is set, it was already skipped
|
||||
// If pointer is nil and omitempty is not set, add nil to map
|
||||
if fieldV.IsNil() {
|
||||
// Only add nil if omitempty is not set (already handled above)
|
||||
if !omitempty {
|
||||
out[key] = nil
|
||||
}
|
||||
continue // Move to next field
|
||||
}
|
||||
// If it points to a struct, dereference and recurse
|
||||
if fieldV.Elem().Kind() == reflect.Struct {
|
||||
nestedMap, err := StructToMap(fieldV.Interface()) // Pass the pointer
|
||||
if err != nil {
|
||||
// Decide how to handle nested errors, e.g., log or return
|
||||
fmt.Printf("Warning: could not convert nested struct pointer %s: %v\n", fieldT.Name, err)
|
||||
out[key] = val // Store original value on error? Or skip?
|
||||
} else {
|
||||
out[key] = nestedMap
|
||||
}
|
||||
continue // Move to next field after handling pointer
|
||||
}
|
||||
// If pointer to non-struct, just get the interface value (handled below)
|
||||
val = fieldV.Interface() // Use the actual pointer value
|
||||
|
||||
} else if fieldV.Kind() == reflect.Struct {
|
||||
// If it's a struct (not a pointer), recurse
|
||||
nestedMap, err := StructToMap(fieldV.Interface()) // Pass the struct value
|
||||
if err != nil {
|
||||
fmt.Printf("Warning: could not convert nested struct %s: %v\n", fieldT.Name, err)
|
||||
out[key] = val // Store original value on error? Or skip?
|
||||
} else {
|
||||
out[key] = nestedMap
|
||||
}
|
||||
continue // Move to next field after handling struct
|
||||
}
|
||||
|
||||
// Assign the value (primitive, slice, map, non-struct pointer, etc.)
|
||||
out[key] = val
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
15
internal/utils/password.go
Normal file
15
internal/utils/password.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func CheckPassword(hash, password string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
@@ -3,3 +3,9 @@ package utils
|
||||
func ToPtr[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
func UpdatePtrField[T any](target *T, value *T) {
|
||||
if value != nil {
|
||||
*target = *value
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user