Working arrays
This commit is contained in:
@ -1,74 +0,0 @@
|
|||||||
package inheritance
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type Model struct{}
|
|
||||||
|
|
||||||
type MyModel struct {
|
|
||||||
Model
|
|
||||||
}
|
|
||||||
|
|
||||||
type MethodInitInterface interface {
|
|
||||||
Init(dbConn int)
|
|
||||||
}
|
|
||||||
|
|
||||||
type RepoBase[T interface{}] struct {
|
|
||||||
DbConn int
|
|
||||||
GetMethod[T]
|
|
||||||
ListMethod[T]
|
|
||||||
methods []MethodInitInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *RepoBase[T]) InitMethods(dbConn int) {
|
|
||||||
for _, method := range b.methods {
|
|
||||||
method.Init(dbConn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CRUDRepo[T interface{}] struct {
|
|
||||||
RepoBase[T]
|
|
||||||
SaveMethod[T]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *CRUDRepo[T]) Init(dbConn int) {
|
|
||||||
m.methods = []MethodInitInterface{&m.GetMethod, &m.ListMethod, &m.SaveMethod}
|
|
||||||
m.InitMethods(dbConn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DoInheritanceTest() {
|
|
||||||
repo := RepoBase[MyModel]{
|
|
||||||
DbConn: 111,
|
|
||||||
// GetMethod: GetMethod{
|
|
||||||
// DbConn: 666,
|
|
||||||
// },
|
|
||||||
// ListMethod: ListMethod{
|
|
||||||
// DbConn: 777,
|
|
||||||
// },
|
|
||||||
}
|
|
||||||
repo.GetMethod.Init(888)
|
|
||||||
repo.ListMethod.Init(888)
|
|
||||||
|
|
||||||
repo.GetMethod.Get()
|
|
||||||
repo.List()
|
|
||||||
|
|
||||||
fmt.Printf("outside Base: %d\n", repo.DbConn)
|
|
||||||
fmt.Printf("outside GetMethod: %d\n", repo.GetMethod.DbConn)
|
|
||||||
fmt.Printf("outside ListMethod: %d\n", repo.ListMethod.DbConn)
|
|
||||||
|
|
||||||
fmt.Println("----------------")
|
|
||||||
|
|
||||||
crudRepo := CRUDRepo[MyModel]{}
|
|
||||||
crudRepo.Init(999)
|
|
||||||
|
|
||||||
crudRepo.Get()
|
|
||||||
crudRepo.List()
|
|
||||||
crudRepo.Save()
|
|
||||||
|
|
||||||
fmt.Printf("outside GetMethod: %d\n", crudRepo.GetMethod.DbConn)
|
|
||||||
fmt.Printf("outside ListMethod: %d\n", crudRepo.ListMethod.DbConn)
|
|
||||||
fmt.Printf("outside SaveMethod: %d\n", crudRepo.SaveMethod.DbConn)
|
|
||||||
|
|
||||||
// repo.DbConn = 123
|
|
||||||
// repo.SomeGetVar = 456
|
|
||||||
// repo.DoSomething()
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
package inheritance
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type GetMethod[T interface{}] struct {
|
|
||||||
SomeGetVar int
|
|
||||||
DbConn int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GetMethod[T]) Init(dbConn int) {
|
|
||||||
m.DbConn = dbConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m GetMethod[T]) Get() T {
|
|
||||||
var model T
|
|
||||||
fmt.Printf("Get DbConn: %d\n", m.DbConn)
|
|
||||||
return model
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListMethod[T interface{}] struct {
|
|
||||||
SomeListVar int
|
|
||||||
DbConn int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ListMethod[T]) Init(dbConn int) {
|
|
||||||
m.DbConn = dbConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m ListMethod[T]) List() {
|
|
||||||
fmt.Printf("List DbConn: %d\n", m.DbConn)
|
|
||||||
}
|
|
||||||
|
|
||||||
type SaveMethod[T interface{}] struct {
|
|
||||||
DbConn int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *SaveMethod[T]) Init(dbConn int) {
|
|
||||||
m.DbConn = dbConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m SaveMethod[T]) Save() {
|
|
||||||
fmt.Printf("List DbConn: %d\n", m.DbConn)
|
|
||||||
}
|
|
||||||
17
app/main.go
17
app/main.go
@ -8,7 +8,6 @@ import (
|
|||||||
"repo-pattern/app/models"
|
"repo-pattern/app/models"
|
||||||
"repo-pattern/app/repository"
|
"repo-pattern/app/repository"
|
||||||
"repo-pattern/app/repository/smartfilter"
|
"repo-pattern/app/repository/smartfilter"
|
||||||
"time"
|
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@ -25,19 +24,19 @@ func doMagic(db *gorm.DB) {
|
|||||||
// id := "6dc096ab-5c03-427e-b808-c669f7446131"
|
// id := "6dc096ab-5c03-427e-b808-c669f7446131"
|
||||||
// serialNumber := "222"
|
// serialNumber := "222"
|
||||||
// serialNumberContains := "323"
|
// serialNumberContains := "323"
|
||||||
issuer := "FINA"
|
// issuer := "FINA"
|
||||||
location, _ := time.LoadLocation("UTC")
|
// location, _ := time.LoadLocation("UTC")
|
||||||
createdTime := time.Date(2024, 5, 26, 16, 8, 0, 0, location)
|
// createdTime := time.Date(2024, 5, 26, 16, 8, 0, 0, location)
|
||||||
ids := []string{"eb2bcac6-5173-4dbb-93b7-e7c03b924a03", "db9fb837-3483-4736-819d-f427dc8cda23", "1fece5e7-8e8d-4828-8298-3b1f07fd29ff"}
|
ids := []string{"eb2bcac6-5173-4dbb-93b7-e7c03b924a03", "db9fb837-3483-4736-819d-f427dc8cda23", "1fece5e7-8e8d-4828-8298-3b1f07fd29ff"}
|
||||||
|
|
||||||
filter := smartfilter.CertFilter{
|
filter := smartfilter.CertFilter{
|
||||||
Alive: &FALSE,
|
// Alive: &FALSE,
|
||||||
// Id: &id,
|
// Id: &id,
|
||||||
// SerialNumber: &serialNumber,
|
// SerialNumber: &serialNumber,
|
||||||
// SerialNumberContains: &serialNumberContains,
|
// SerialNumberContains: &serialNumberContains,
|
||||||
Ids: &ids,
|
Ids: &ids,
|
||||||
IssuerContains: &issuer,
|
// IssuerContains: &issuer,
|
||||||
CreatedAt_Lt: &createdTime,
|
// CreatedAt_Lt: &createdTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
query, err = smartfilter.ToQuery(models.Cert{}, filter, query)
|
query, err = smartfilter.ToQuery(models.Cert{}, filter, query)
|
||||||
@ -113,9 +112,9 @@ func main() {
|
|||||||
db := db.InitDB()
|
db := db.InitDB()
|
||||||
repository.Dao = repository.CreateDAO(db)
|
repository.Dao = repository.CreateDAO(db)
|
||||||
|
|
||||||
// doMagic(db)
|
doMagic(db)
|
||||||
// doList(db)
|
// doList(db)
|
||||||
// doGet(db)
|
// doGet(db)
|
||||||
doExists(db)
|
// doExists(db)
|
||||||
// inheritance.DoInheritanceTest()
|
// inheritance.DoInheritanceTest()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,11 @@ type FilterField struct {
|
|||||||
uintValue *uint64
|
uintValue *uint64
|
||||||
floatValue *float64
|
floatValue *float64
|
||||||
strValue *string
|
strValue *string
|
||||||
|
boolValues *[]bool
|
||||||
|
intValues *[]int64
|
||||||
|
uintValues *[]uint64
|
||||||
|
floatValues *[]float64
|
||||||
|
strValues *[]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ff *FilterField) setValueFromReflection(v reflect.Value) {
|
func (ff *FilterField) setValueFromReflection(v reflect.Value) {
|
||||||
@ -23,6 +28,71 @@ func (ff *FilterField) setValueFromReflection(v reflect.Value) {
|
|||||||
fn(ff, v)
|
fn(ff, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ff *FilterField) appendStr(value string) {
|
||||||
|
var valueArray []string
|
||||||
|
|
||||||
|
if ff.strValues == nil {
|
||||||
|
valueArray = make([]string, 0)
|
||||||
|
} else {
|
||||||
|
valueArray = *ff.strValues
|
||||||
|
}
|
||||||
|
valueArray = append(valueArray, value)
|
||||||
|
ff.strValues = &valueArray
|
||||||
|
ff.valueKind = reflect.String
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ff *FilterField) appendBool(value bool) {
|
||||||
|
var valueArray []bool
|
||||||
|
|
||||||
|
if ff.boolValues == nil {
|
||||||
|
valueArray = make([]bool, 0)
|
||||||
|
} else {
|
||||||
|
valueArray = *ff.boolValues
|
||||||
|
}
|
||||||
|
valueArray = append(valueArray, value)
|
||||||
|
ff.boolValues = &valueArray
|
||||||
|
ff.valueKind = reflect.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ff *FilterField) appendInt(value int64) {
|
||||||
|
var valueArray []int64
|
||||||
|
|
||||||
|
if ff.boolValues == nil {
|
||||||
|
valueArray = make([]int64, 0)
|
||||||
|
} else {
|
||||||
|
valueArray = *ff.intValues
|
||||||
|
}
|
||||||
|
valueArray = append(valueArray, value)
|
||||||
|
ff.intValues = &valueArray
|
||||||
|
ff.valueKind = reflect.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ff *FilterField) appendUint(value uint64) {
|
||||||
|
var valueArray []uint64
|
||||||
|
|
||||||
|
if ff.boolValues == nil {
|
||||||
|
valueArray = make([]uint64, 0)
|
||||||
|
} else {
|
||||||
|
valueArray = *ff.uintValues
|
||||||
|
}
|
||||||
|
valueArray = append(valueArray, value)
|
||||||
|
ff.uintValues = &valueArray
|
||||||
|
ff.valueKind = reflect.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ff *FilterField) appendFloat(value float64) {
|
||||||
|
var valueArray []float64
|
||||||
|
|
||||||
|
if ff.boolValues == nil {
|
||||||
|
valueArray = make([]float64, 0)
|
||||||
|
} else {
|
||||||
|
valueArray = *ff.floatValues
|
||||||
|
}
|
||||||
|
valueArray = append(valueArray, value)
|
||||||
|
ff.floatValues = &valueArray
|
||||||
|
ff.valueKind = reflect.Int
|
||||||
|
}
|
||||||
|
|
||||||
type valueGetterFunc func(ff *FilterField, v reflect.Value) error
|
type valueGetterFunc func(ff *FilterField, v reflect.Value) error
|
||||||
|
|
||||||
func boolValueGetter(ff *FilterField, v reflect.Value) error {
|
func boolValueGetter(ff *FilterField, v reflect.Value) error {
|
||||||
@ -121,8 +191,8 @@ func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc {
|
|||||||
// return newMapEncoder(t)
|
// return newMapEncoder(t)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return newSliceGetter(t)
|
return newSliceGetter(t)
|
||||||
case reflect.Array:
|
// case reflect.Array:
|
||||||
return newArrayGetter(t)
|
// return newArrayGetter(t)
|
||||||
case reflect.Pointer:
|
case reflect.Pointer:
|
||||||
return newPtrValueGetter(t)
|
return newPtrValueGetter(t)
|
||||||
}
|
}
|
||||||
@ -130,44 +200,64 @@ func newTypeGetter(t reflect.Type, allowAddr bool) valueGetterFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ptrValueGetter struct {
|
type ptrValueGetter struct {
|
||||||
elemEnc valueGetterFunc
|
elemGetter valueGetterFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pvg ptrValueGetter) getValue(ff *FilterField, v reflect.Value) error {
|
func (pvg ptrValueGetter) getValue(ff *FilterField, v reflect.Value) error {
|
||||||
pvg.elemEnc(ff, v.Elem())
|
pvg.elemGetter(ff, v.Elem())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPtrValueGetter(t reflect.Type) valueGetterFunc {
|
func newPtrValueGetter(t reflect.Type) valueGetterFunc {
|
||||||
enc := ptrValueGetter{elemEnc: typeGetter(t.Elem())}
|
enc := ptrValueGetter{elemGetter: typeGetter(t.Elem())}
|
||||||
return enc.getValue
|
return enc.getValue
|
||||||
}
|
}
|
||||||
|
|
||||||
type arrayGetter struct {
|
type arrayGetter struct {
|
||||||
elemEnc valueGetterFunc
|
elemGetter valueGetterFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ag arrayGetter) getValue(ff *FilterField, v reflect.Value) error {
|
func (ag arrayGetter) getValue(ff *FilterField, v reflect.Value) error {
|
||||||
ag.elemEnc(ff, v.Elem())
|
ag.elemGetter(ff, v.Elem())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArrayGetter(t reflect.Type) valueGetterFunc {
|
func newArrayGetter(t reflect.Type) valueGetterFunc {
|
||||||
enc := arrayGetter{elemEnc: typeGetter(t.Elem())}
|
enc := arrayGetter{elemGetter: typeGetter(t.Elem())}
|
||||||
return enc.getValue
|
return enc.getValue
|
||||||
}
|
}
|
||||||
|
|
||||||
type sliceGetter struct {
|
type sliceGetter struct {
|
||||||
elemEnc valueGetterFunc
|
elemGetter valueGetterFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sg sliceGetter) getValue(ff *FilterField, v reflect.Value) error {
|
func (sg sliceGetter) getValue(ff *FilterField, v reflect.Value) error {
|
||||||
fmt.Printf("%+v\n", v.Slice(0, 1))
|
for n := range v.Len() {
|
||||||
sg.elemEnc(ff, v.Elem())
|
element := v.Index(n)
|
||||||
|
fmt.Printf("ELEMENT: %+v\n", element)
|
||||||
|
|
||||||
|
switch element.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
ff.appendBool(element.Bool())
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
ff.appendInt(element.Int())
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
ff.appendUint(element.Uint())
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
ff.appendFloat(element.Float())
|
||||||
|
case reflect.String:
|
||||||
|
ff.appendStr(element.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println(v.Len())
|
||||||
|
fmt.Printf(">>> getValue %+v\n", v)
|
||||||
|
fmt.Printf(">>> ff %+v\n", ff.strValues)
|
||||||
|
// fmt.Printf("%+v\n", v.Slice(0, 1))
|
||||||
|
// sg.elemGetter(ff, v.Elem())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSliceGetter(t reflect.Type) valueGetterFunc {
|
func newSliceGetter(t reflect.Type) valueGetterFunc {
|
||||||
enc := sliceGetter{elemEnc: typeGetter(t.Elem())}
|
enc := sliceGetter{elemGetter: newArrayGetter(t)}
|
||||||
return enc.getValue
|
return enc.getValue
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,7 +51,13 @@ func applyFilterLE[T bool | int64 | uint64 | float64 | string](
|
|||||||
}
|
}
|
||||||
|
|
||||||
func applyFilterIN[T bool | int64 | uint64 | float64 | string](
|
func applyFilterIN[T bool | int64 | uint64 | float64 | string](
|
||||||
query *gorm.DB, tableName string, filterField *FilterField, value T,
|
query *gorm.DB, tableName string, filterField *FilterField, value *[]T,
|
||||||
) *gorm.DB {
|
) *gorm.DB {
|
||||||
return query.Where(fmt.Sprintf("%s.%s IN ?", tableName, filterField.Name), value)
|
return query.Where(fmt.Sprintf("%s.%s IN (?)", tableName, filterField.Name), *value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyFilterNOT_IN[T bool | int64 | uint64 | float64 | string](
|
||||||
|
query *gorm.DB, tableName string, filterField *FilterField, value *[]T,
|
||||||
|
) *gorm.DB {
|
||||||
|
return query.Where(fmt.Sprintf("%s.%s NOT IN (?)", tableName, filterField.Name), *value)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,14 +112,32 @@ func handleOperatorLE(query *gorm.DB, tableName string, filterField *FilterField
|
|||||||
|
|
||||||
func handleOperatorIN(query *gorm.DB, tableName string, filterField *FilterField) *gorm.DB {
|
func handleOperatorIN(query *gorm.DB, tableName string, filterField *FilterField) *gorm.DB {
|
||||||
switch filterField.valueKind {
|
switch filterField.valueKind {
|
||||||
|
case reflect.Bool:
|
||||||
|
return applyFilterIN(query, tableName, filterField, filterField.boolValues)
|
||||||
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
return applyFilterIN(query, tableName, filterField, *filterField.intValue)
|
return applyFilterIN(query, tableName, filterField, filterField.intValues)
|
||||||
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
return applyFilterIN(query, tableName, filterField, *filterField.uintValue)
|
return applyFilterIN(query, tableName, filterField, filterField.uintValues)
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
return applyFilterIN(query, tableName, filterField, *filterField.floatValue)
|
return applyFilterIN(query, tableName, filterField, filterField.floatValues)
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return applyFilterIN(query, tableName, filterField, *filterField.strValue)
|
return applyFilterIN(query, tableName, filterField, filterField.strValues)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleOperatorNOT_IN(query *gorm.DB, tableName string, filterField *FilterField) *gorm.DB {
|
||||||
|
switch filterField.valueKind {
|
||||||
|
case reflect.Bool:
|
||||||
|
return applyFilterNOT_IN(query, tableName, filterField, filterField.boolValues)
|
||||||
|
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return applyFilterNOT_IN(query, tableName, filterField, filterField.intValues)
|
||||||
|
case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
return applyFilterNOT_IN(query, tableName, filterField, filterField.uintValues)
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return applyFilterNOT_IN(query, tableName, filterField, filterField.floatValues)
|
||||||
|
case reflect.String:
|
||||||
|
return applyFilterNOT_IN(query, tableName, filterField, filterField.strValues)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,11 +12,12 @@ const (
|
|||||||
OperatorLIKE Operator = "LIKE"
|
OperatorLIKE Operator = "LIKE"
|
||||||
OperatorILIKE Operator = "ILIKE"
|
OperatorILIKE Operator = "ILIKE"
|
||||||
OperatorIN Operator = "IN"
|
OperatorIN Operator = "IN"
|
||||||
|
OperatorNOT_IN Operator = "NOT_IN"
|
||||||
)
|
)
|
||||||
|
|
||||||
var OPERATORS = []Operator{
|
var OPERATORS = []Operator{
|
||||||
OperatorEQ, OperatorNE,
|
OperatorEQ, OperatorNE,
|
||||||
OperatorGT, OperatorGE, OperatorLT, OperatorLE,
|
OperatorGT, OperatorGE, OperatorLT, OperatorLE,
|
||||||
OperatorLIKE, OperatorILIKE,
|
OperatorLIKE, OperatorILIKE,
|
||||||
OperatorIN,
|
OperatorIN, OperatorNOT_IN,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ var operatorHandlers = map[Operator]handlerFunc{
|
|||||||
OperatorLIKE: handleOperatorLIKE,
|
OperatorLIKE: handleOperatorLIKE,
|
||||||
OperatorILIKE: handleOperatorILIKE,
|
OperatorILIKE: handleOperatorILIKE,
|
||||||
OperatorIN: handleOperatorIN,
|
OperatorIN: handleOperatorIN,
|
||||||
|
OperatorNOT_IN: handleOperatorNOT_IN,
|
||||||
}
|
}
|
||||||
|
|
||||||
type CertFilter struct {
|
type CertFilter struct {
|
||||||
@ -35,6 +36,7 @@ type CertFilter struct {
|
|||||||
IssuerContains *string `filterfield:"issuer,ILIKE"`
|
IssuerContains *string `filterfield:"issuer,ILIKE"`
|
||||||
Id *string `filterfield:"id,EQ"`
|
Id *string `filterfield:"id,EQ"`
|
||||||
Ids *[]string `filterfield:"id,IN"`
|
Ids *[]string `filterfield:"id,IN"`
|
||||||
|
IdsNot *[]string `filterfield:"id,NOT_IN"`
|
||||||
CreatedAt_Lt *time.Time `filterfield:"created_at,LT"`
|
CreatedAt_Lt *time.Time `filterfield:"created_at,LT"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +75,8 @@ func getFilterFields(filter interface{}) []ReflectedStructField {
|
|||||||
value: fieldValue,
|
value: fieldValue,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fmt.Println("-------------- RES --------------")
|
||||||
|
fmt.Printf("%+v\n", res)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user