Skip to content

Instantly share code, notes, and snippets.

@ahmedalkabir
Created March 13, 2024 06:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahmedalkabir/5cd538c0b485e952f9fd6f0b11be22e7 to your computer and use it in GitHub Desktop.
Save ahmedalkabir/5cd538c0b485e952f9fd6f0b11be22e7 to your computer and use it in GitHub Desktop.
Option Monadic operation implementation
package option
type Option[T any] struct {
value T
isFull bool
}
func Some[T any](value T) Option[T] {
return Option[T]{value: value, isFull: true}
}
func None[T any]() Option[T] {
return Option[T]{isFull: false}
}
func (s *Option[T]) Get() T {
if s.isFull {
return s.value
} else {
panic("cannot get from None type")
}
}
func (s *Option[T]) GetOrElse(other T) T {
if s.isFull {
return s.value
} else {
return other
}
}
func (s *Option[_]) IsEmpty() bool {
return !s.isFull
}
func (s Option[T]) String() string {
if s.isFull {
return fmt.Sprintf("Some(%v)", s.value)
} else {
return "None"
}
}
func (s Option[_]) MarshalJSON() ([]byte, error) {
if s.isFull {
return json.Marshal(s.value)
} else {
return []byte("null"), nil
}
}
func (s *Option[_]) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
s.isFull = false
return nil
}
err := json.Unmarshal(data, &s.value)
if err != nil {
return err
}
s.isFull = true
return nil
}
// UnmarshalParam to find form values of echo binder
func (s *Option[_]) UnmarshalParam(src string) error {
s_type := reflect.TypeOf(s.value).Kind()
switch s_type {
case reflect.String:
rv := reflect.ValueOf(&s.value)
if rv.Kind() != reflect.Pointer || rv.IsNil() {
return errors.New("failed: to unmarshal value")
}
rv.Elem().SetString(src)
s.isFull = true
case reflect.Int:
number, err := strconv.ParseInt(src, 10, 64)
if err != nil {
return errors.New("failed: to unmarshal value")
}
rv := reflect.ValueOf(&s.value)
if rv.Kind() != reflect.Pointer || rv.IsNil() {
return errors.New("failed: to unmarshal value")
}
rv.Elem().SetInt(number)
s.isFull = true
case reflect.Bool:
status := validation.StringToBoolean(src)
rv := reflect.ValueOf(&s.value)
if rv.Kind() != reflect.Pointer || rv.IsNil() {
return errors.New("failed: to unmarshal value")
}
rv.Elem().SetBool(status)
s.isFull = true
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment