My core stuff with types, code, etc that I use almost everywhere
You can check if a slice contains a value with Contains
method:
slice := []int{1, 2, 3, 4, 5}
fmt.Println(core.Contains(slice, 4)) // true
fmt.Println(core.Contains(slice, 6)) // false
Contains
works with all comparable
types.
If the slice type is more complex, you can use ContainsWithFunc
method:
type User struct {
ID int
Name string
}
slice := []User{
{ID: 1, Name: "John"},
{ID: 2, Name: "Jane"},
{ID: 3, Name: "Bob"},
}
fmt.Println(core.ContainsWithFunc(slice, User{Name: "John"}, func(a, b User) bool {
return a.Name == b.Name
})) // true
You can check if two slices are equal with EqualSlices
method:
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{1, 2, 3, 4, 5}
fmt.Println(core.EqualSlices(slice1, slice2)) // true
EqualSlices
works with all comparable
types.
If the slice type is more complex, you can use EqualSlicesWithFunc
method:
type User struct {
ID int
Name string
}
slice1 := []User{
{ID: 1, Name: "John"},
{ID: 2, Name: "Jane"},
{ID: 3, Name: "Bob"},
}
slice2 := []User{
{ID: 1, Name: "John"},
{ID: 2, Name: "Jane"},
{ID: 3, Name: "Bob"},
}
fmt.Println(core.EqualSlicesWithFunc(slice1, slice2, func(a, b User) bool {
return a.Name == b.Name
})) // true
You can filter a slice with Filter
method:
slice := []int{1, 2, 3, 4, 5}
fmt.Println(core.Filter(slice, func(element int) bool {
return element > 3
})) // [4 5]
You can join a slice with Join
method:
slice := []int{1, 2, 3, 4, 5}
fmt.Println(core.Join(slice, ",")) // 1,2,3,4,5
If the slice type is more complex, you can use JoinWithFunc
method:
type User struct {
ID int
Name string
}
slice := []User{
{ID: 1, Name: "John"},
{ID: 2, Name: "Jane"},
{ID: 3, Name: "Bob"},
}
fmt.Println(core.JoinWithFunc(slice, ",", func(element User) string {
return element.Name
})) // John,Jane,Bob
You can map a slice with Map
method:
slice := []int{1, 2, 3, 4, 5}
fmt.Println(core.Map(slice, func(element int) int {
return element * 2
})) // [2 4 6 8 10]
The returned slice is a new slice, the original slice is not modified.
You can reduce a slice with Reduce
method:
slice := []int{1, 2, 3, 4, 5}
fmt.Println(core.Reduce(slice, func(accumulator, element int) int {
return accumulator + element
})) // 15
You can sort a slice with Sort
method:
slice := []int{5, 2, 3, 1, 4}
fmt.Println(core.Sort(slice, func(a, b int) {
return a < b
})) // [1 2 3 4 5]
The Sort
method uses a simple Quick Sort algorithm.
The core.Time
mimics the time.Time
and adds JSON serialization support to and from RFC 3339 time strings.
The core.Duration
mimics the time.Duration
and adds JSON serialization support to and from duration strings. Its core.ParseDuration
also understands most of the ISO 8601 duration formats. It marshals to milliseconds. It can unmarshal from milliseconds, GO duration strings, and ISO 8601 duration strings.
Example:
type User struct {
Name string
CreatedAt core.Time
Duration core.Duration
}
user := User{
Name: "John",
CreatedAt: core.Now(),
Duration: core.Duration(5 * time.Second),
}
data, err := json.Marshal(user)
if err != nil {
panic(err)
}
fmt.Println(string(data))
// {"Name":"John","CreatedAt":"2021-01-01T00:00:00Z","Duration":"5000"}
string.Replace(string(data), "5000", "PT5S", 1)
var user2 User
err = json.Unmarshal(data, &user2)
if err != nil {
panic(err)
}
fmt.Println(user2.Duration) // 5s
The core.Timestamp
type is an alias for core.Time
and it is used to represent timestamps in milliseconds. It marshals into milliseconds and unmarshals from milliseconds (string or integer).
You can get an environment variable with GetEnvAsX
method, where X
is one of bool
, time.Duration
, string
, time.Time
, url.URL
, uuid.UUID
, if the environment variable is not set or the conversion fails, the default value is returned.
Example:
// GetEnvAsBool
v := core.GetEnvAsBool("ENV_VAR", false)
// GetEnvAsDuration
v := core.GetEnvAsDuration("ENV_VAR", 5 * time.Second)
// GetEnvAsString
v := core.GetEnvAsString("ENV_VAR", "default")
// GetEnvAsTime
v := core.GetEnvAsTime("ENV_VAR", time.Now())
// GetEnvAsURL
v := core.GetEnvAsURL("ENV_VAR", &url.URL{Scheme: "https", Host: "example.com"})
// GetEnvAsUUID
v := core.GetEnvAsUUID("ENV_VAR", uuid.New())
Notes:
GetEnvAsBool
returnstrue
if the environment variable is set totrue
,1
,on
oryes
, otherwise it returnsfalse
. It is also case-insensitive.GetEnvAsDuration
accepts any duration string that can be parsed bycore.ParseDuration
.GetEnvAsTime
accepts an RFC 3339 time string.GetEnvAsURL
fallback can be aurl.URL
, a*url.URL
, or astring
.
The core.Identifiable
interface is used to represent an object that has an ID in the form of a uuid.UUID
.
The core.Nameable
interface is used to represent an object that has a name in the form of a string
.
The core.IsZeroer
interface is used to represent an object that can be checked if it is zero.
The core.GoString
interface is used to represent an object that can be converted to a Go string.
core.RespondWithJSON
is a helper function that marshals a payload into an http.ResponseWriter
as JSON. It also sets the Content-Type
header to application/json
.
core.RespondWithHTMLTemplate
is a helper function that executes a template on a given data and writes the result into an http.ResponseWriter
. It also sets the Content-Type
header to text/html
.
core.RespondWithError
is a helper function that marshals an error into an http.ResponseWriter
as JSON. It also sets the Content-Type
header to application/json
.
ExecEvery
executes a function every duration
:
stop, ping, change := core.ExecEvery(5 * time.Second, func() {
fmt.Println("ping")
})
time.Sleep(15 * time.Second)
change <- 10 * time.Second
time.Sleep(15 * time.Second)
stop <- true
Notes:
stop
is a channel that can be used to stop the execution.ping
is a channel that can be used to force the execution of the func at any time.change
is a channel that can be used to change the execution duration.
FlexInt
, FlexInt8
, FlexInt16
, FlexInt32
, FlexInt64
are types that can be unmarshalled from a string or an integer:
type User struct {
ID core.FlexInt
}
user := User{}
json.Unmarshal([]byte(`{"ID": 1}`), &user)
json.Unmarshal([]byte(`{"ID": "1"}`), &user)
core.Must
is a helper function that panics if the error is not nil
from a function that returns a value and an error:
func DoSomething() (string, error) {
return "", errors.New("error")
}
func main() {
value := core.Must(DoSomething()).(string)
}
core.URL
is an alias for url.URL
that marshals as a string and unmarshals from a string. When unmarshaling, if the value is nil or empty, the unmarshaled value is nil (it is not considered as an error).
core.UUID
is an alias for uuid.UUID
that marshals as a string and unmarshals from a string. When unmarshaling, if the value is nil or empty, the unmarshaled value is uuid.Nil
(it is not considered as an error).
core.TypeRegistry
is a type registry that can be used to unmarshal JSON core.TypeCarrier
objects into the correct type:
type User struct {
ID uuid.UUID
Name string
}
func (user User) GetType() string {
return "user"
}
type Product struct {
ID uuid.UUID
Name string
}
func (product Product) GetType() string {
return "product"
}
registry := core.NewTypeRegistry()
registry.Add(User{}, Product{})
var user User
err := registry.UnmarshalJSON([]byte(`{"type": "user", "ID": "00000000-0000-0000-0000-000000000000", "Name": "John"}`), &user)
if err != nil {
panic(err)
}
fmt.Println(user)
Notes:
- The default JSON property name for the type is
type
, but it can be changed by adding strings to the UnmarshalJSON method.