Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
0652bf22dc
|
|||
b196adffc7
|
|||
717065e62d
|
@@ -61,3 +61,43 @@ func CompareArr[T OrderedConstraint](arr1 []T, arr2 []T) bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func CompareString(a, b string) int {
|
||||
if a == b {
|
||||
return 0
|
||||
}
|
||||
if a < b {
|
||||
return -1
|
||||
}
|
||||
return +1
|
||||
}
|
||||
|
||||
func CompareInt(a, b int) int {
|
||||
if a == b {
|
||||
return 0
|
||||
}
|
||||
if a < b {
|
||||
return -1
|
||||
}
|
||||
return +1
|
||||
}
|
||||
|
||||
func CompareInt64(a, b int64) int {
|
||||
if a == b {
|
||||
return 0
|
||||
}
|
||||
if a < b {
|
||||
return -1
|
||||
}
|
||||
return +1
|
||||
}
|
||||
|
||||
func Compare[T OrderedConstraint](a, b T) int {
|
||||
if a == b {
|
||||
return 0
|
||||
}
|
||||
if a < b {
|
||||
return -1
|
||||
}
|
||||
return +1
|
||||
}
|
||||
|
111
langext/reflection.go
Normal file
111
langext/reflection.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package langext
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var reflectBasicTypes = []reflect.Type{
|
||||
reflect.Bool: reflect.TypeOf(false),
|
||||
reflect.Int: reflect.TypeOf(int(0)),
|
||||
reflect.Int8: reflect.TypeOf(int8(0)),
|
||||
reflect.Int16: reflect.TypeOf(int16(0)),
|
||||
reflect.Int32: reflect.TypeOf(int32(0)),
|
||||
reflect.Int64: reflect.TypeOf(int64(0)),
|
||||
reflect.Uint: reflect.TypeOf(uint(0)),
|
||||
reflect.Uint8: reflect.TypeOf(uint8(0)),
|
||||
reflect.Uint16: reflect.TypeOf(uint16(0)),
|
||||
reflect.Uint32: reflect.TypeOf(uint32(0)),
|
||||
reflect.Uint64: reflect.TypeOf(uint64(0)),
|
||||
reflect.Uintptr: reflect.TypeOf(uintptr(0)),
|
||||
reflect.Float32: reflect.TypeOf(float32(0)),
|
||||
reflect.Float64: reflect.TypeOf(float64(0)),
|
||||
reflect.Complex64: reflect.TypeOf(complex64(0)),
|
||||
reflect.Complex128: reflect.TypeOf(complex128(0)),
|
||||
reflect.String: reflect.TypeOf(""),
|
||||
}
|
||||
|
||||
// Underlying returns the underlying type of t (without type alias)
|
||||
//
|
||||
// https://github.com/golang/go/issues/39574#issuecomment-655664772
|
||||
func Underlying(t reflect.Type) (ret reflect.Type) {
|
||||
if t.Name() == "" {
|
||||
// t is an unnamed type. the underlying type is t itself
|
||||
return t
|
||||
}
|
||||
kind := t.Kind()
|
||||
if ret = reflectBasicTypes[kind]; ret != nil {
|
||||
return ret
|
||||
}
|
||||
switch kind {
|
||||
case reflect.Array:
|
||||
ret = reflect.ArrayOf(t.Len(), t.Elem())
|
||||
case reflect.Chan:
|
||||
ret = reflect.ChanOf(t.ChanDir(), t.Elem())
|
||||
case reflect.Map:
|
||||
ret = reflect.MapOf(t.Key(), t.Elem())
|
||||
case reflect.Func:
|
||||
nIn := t.NumIn()
|
||||
nOut := t.NumOut()
|
||||
in := make([]reflect.Type, nIn)
|
||||
out := make([]reflect.Type, nOut)
|
||||
for i := 0; i < nIn; i++ {
|
||||
in[i] = t.In(i)
|
||||
}
|
||||
for i := 0; i < nOut; i++ {
|
||||
out[i] = t.Out(i)
|
||||
}
|
||||
ret = reflect.FuncOf(in, out, t.IsVariadic())
|
||||
case reflect.Interface:
|
||||
// not supported
|
||||
case reflect.Ptr:
|
||||
ret = reflect.PtrTo(t.Elem())
|
||||
case reflect.Slice:
|
||||
ret = reflect.SliceOf(t.Elem())
|
||||
case reflect.Struct:
|
||||
// only partially supported: embedded fields
|
||||
// and unexported fields may cause panic in reflect.StructOf()
|
||||
defer func() {
|
||||
// if a panic happens, return t unmodified
|
||||
if recover() != nil && ret == nil {
|
||||
ret = t
|
||||
}
|
||||
}()
|
||||
n := t.NumField()
|
||||
fields := make([]reflect.StructField, n)
|
||||
for i := 0; i < n; i++ {
|
||||
fields[i] = t.Field(i)
|
||||
}
|
||||
ret = reflect.StructOf(fields)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// TryCast works similar to `v2, ok := v.(T)`
|
||||
// Except it works through type alias'
|
||||
func TryCast[T any](v any) (T, bool) {
|
||||
|
||||
underlying := Underlying(reflect.TypeOf(v))
|
||||
|
||||
def := *new(T)
|
||||
|
||||
if underlying != Underlying(reflect.TypeOf(def)) {
|
||||
return def, false
|
||||
}
|
||||
|
||||
r1 := reflect.ValueOf(v)
|
||||
|
||||
if !r1.CanConvert(underlying) {
|
||||
return def, false
|
||||
}
|
||||
|
||||
r2 := r1.Convert(underlying)
|
||||
|
||||
r3 := r2.Interface()
|
||||
|
||||
r4, ok := r3.(T)
|
||||
if !ok {
|
||||
return def, false
|
||||
}
|
||||
|
||||
return r4, true
|
||||
}
|
@@ -22,6 +22,31 @@ func Max[T langext.OrderedConstraint](v1 T, v2 T) T {
|
||||
}
|
||||
}
|
||||
|
||||
func Max3[T langext.OrderedConstraint](v1 T, v2 T, v3 T) T {
|
||||
result := v1
|
||||
if v2 > result {
|
||||
result = v2
|
||||
}
|
||||
if v3 > result {
|
||||
result = v3
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func Max4[T langext.OrderedConstraint](v1 T, v2 T, v3 T, v4 T) T {
|
||||
result := v1
|
||||
if v2 > result {
|
||||
result = v2
|
||||
}
|
||||
if v3 > result {
|
||||
result = v3
|
||||
}
|
||||
if v4 > result {
|
||||
result = v4
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func Min[T langext.OrderedConstraint](v1 T, v2 T) T {
|
||||
if v1 < v2 {
|
||||
return v1
|
||||
@@ -30,6 +55,31 @@ func Min[T langext.OrderedConstraint](v1 T, v2 T) T {
|
||||
}
|
||||
}
|
||||
|
||||
func Min3[T langext.OrderedConstraint](v1 T, v2 T, v3 T) T {
|
||||
result := v1
|
||||
if v2 < result {
|
||||
result = v2
|
||||
}
|
||||
if v3 < result {
|
||||
result = v3
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func Min4[T langext.OrderedConstraint](v1 T, v2 T, v3 T, v4 T) T {
|
||||
result := v1
|
||||
if v2 < result {
|
||||
result = v2
|
||||
}
|
||||
if v3 < result {
|
||||
result = v3
|
||||
}
|
||||
if v4 < result {
|
||||
result = v4
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func Abs[T langext.NumberConstraint](v T) T {
|
||||
if v < 0 {
|
||||
return -v
|
||||
|
Reference in New Issue
Block a user