Utils (pointer & conversion helpers)
gitlab.finema.co/finema/idin-core/v2/utils — small, dependency-free generics for the pointer/enum juggling that request→model mapping needs.
Pointer basics
go
p := utils.ToPointer("hello") // string → *string
v := utils.ToNonPointer(p) // *string → string (zero value if nil)
v := utils.ToNonPointerOr(p, "def") // *string → string, "def" if nilConverting enum pointers
A request DTO usually carries *string, while the model wants *SomeEnum (a type SomeEnum string). Instead of the verbose deref → convert → re-pointer:
go
// before — long and easy to get wrong
var projectType *models.PMOProjectType
if input.Type != nil {
projectType = utils.ToPointer(models.PMOProjectType(utils.ToNonPointer(input.Type)))
}
// after — one nil-safe call
projectType := utils.PtrConvert[models.PMOProjectType](input.Type)Inline in a struct literal it stays short:
go
pmoProject := &models.PMOProject{
BaseModel: models.NewBaseModel(),
Name: input.Name,
Status: models.PMOProjectStatusIntro,
Type: utils.PtrConvert[models.PMOProjectType](input.Type), // *string → *PMOProjectType
Code: input.Code,
CreatedByID: utils.ToPointer(s.ctx.GetUser().ID),
}It works both ways (e.g. building an output DTO):
go
resp.Type = utils.PtrConvert[string](pmoProject.Type) // *PMOProjectType → *stringR is given explicitly; the source type is inferred; nil in → nil out.
Numeric enums
For type Priority int and friends use PtrConvertNum:
go
priority := utils.PtrConvertNum[models.Priority](input.Priority) // *int → *models.PriorityAnything else — MapPtr
For non-trivial conversions (structs, formatting), pass a function; still nil-safe:
go
createdAt := utils.MapPtr(model.CreatedAt, func(t time.Time) string {
return t.Format(time.RFC3339)
})API
go
func ToPointer[T any](v T) *T
func ToNonPointer[T any](p *T) T
func ToNonPointerOr[T any](p *T, def T) T
func PtrConvert[R ~string, T ~string](p *T) *R // string enums
func PtrConvertNum[R Numeric, T Numeric](p *T) *R // numeric enums
func MapPtr[T, R any](p *T, fn func(T) R) *R // custom conversionsSlices
go
utils.DerefSlice([]*string{p1, nil, p3}) // []*T → []T (zero for nil)
utils.PtrSlice([]int{1, 2}) // []T → []*T
utils.Map([]int{1, 2}, func(n int) int { return n*2 }) // → [2 4]
utils.Filter(xs, func(x T) bool { return ... })
utils.Contains([]string{"a", "b"}, "b") // true
utils.Unique([]int{1, 2, 2, 3}) // [1 2 3]JSON & structs
go
utils.JSONToString(v) // compact JSON string ("" on error)
utils.StructToString(v) // pretty (indented) JSON string
utils.MapToStruct(src, &dst) // struct/map → struct via JSON
utils.MapTo[User](src) // generic: returns (User, error)
utils.StructToMap(v) // → map[string]any
utils.JSONParse(body, &dst) // unmarshal with a friendly type-error message
utils.Copy(&dst, src) // deep copy matching fields (jinzhu/copier)
utils.IsEmpty(x) // nil or zero value (any)
utils.IsZero(v) // zero value (comparable, generic)UUID / time
go
utils.NewUUID() // random UUID string
utils.IsUUID(s) // validate (fixed vs v1)
utils.ParseUUID(s) // (uuid.UUID, error)
utils.NowPtr() // *time.Time = nowCrypto / encoding
go
utils.SHA256(s) / SHA384(s) / SHA512(s) // hex digests
utils.MD5(s) // checksums/etags only (not security)
utils.Base64Encode(s) / Base64Decode(s)
utils.HexEncode(b) / HexDecode(s)
utils.HashPassword(pw) // bcrypt → (string, error)
utils.ComparePassword(hash, pw) // boolChanges from v1
| v1 | v2 |
|---|---|
GetString/GetInt/GetBool/… | ToNonPointer[T] (generic) + ToNonPointerOr |
GetArrayString | DerefSlice[T] (generic) |
GetUUID | NewUUID |
GetCurrentDateTime | NowPtr |
NewSha256/384/512 | SHA256/384/512 |
GetMD5Hash | MD5 |
HashPassword returns *string | returns string |
IsUUID (broken FromBytes) | fixed (uuid.Parse) |
DID / ECDSA-RSA keypairs / sign-verify / GetBigNumber (0x/0b) / MockExplorer | removed — domain-specific, belongs in the consuming service |
utils.IsStrIn / IsExists (govalidator+gorm) | removed — use the valid package |