A
A
Andrey Gorbik2021-05-20 17:40:06
go
Andrey Gorbik, 2021-05-20 17:40:06

How to test nil interface?

package main

import (
  "fmt"
  "strings"
)

// Есть такой интерфейс:
type validator interface {
  Validate() error
}

// есть такой тип, удовлетворяющий интерфейсу:
type FieldEmail string

func (fi FieldEmail) Validate() error {
  if !strings.Contains(string(fi), "@") {
    return fmt.Errorf("invalid field")
  }

  return nil
}

// Есть общая функция, которая проверяет поля:
func checkValidators(validators ...validator) error {
  for _, v := range validators {
    if v == nil { // здесь ошибка
      continue
    }
    if err := v.Validate(); err != nil {
      return err
    }
  }
  return nil
}

func main() {
  // здесь проблемы нет
  fmt.Printf("Error: %v\n", checkValidators(FieldEmail("[email protected]")))

  // но если у меня *FieldEmail, то в checkValidators условие `v == nil` не срабатывает
  var email *FieldEmail
  fmt.Printf("Error: %v\n", checkValidators(email))
}


Because *FieldEmail is actually a structure field and there are many such fields, I don't want to check each field for != nil before passing it to the checkValidators() function.


The solution I found uses reflection, which I would also like to avoid.

Code on the playground

Any ideas how else to implement this?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexander Pavlyuk, 2021-05-20
@and_gorbik

You can for example like this:

package main

import (
  "errors"
  "fmt"
  "strings"
)

type validator interface {
  Validate() error
}

type FieldEmail string

func (fi *FieldEmail) Validate() error {
  if fi == nil {
    return errors.New("invalid field")
  }

  if !strings.Contains(string(*fi), "@") {
    return errors.New("invalid field")
  }

  return nil
}

func NewFieldEmail(str string) *FieldEmail {
  fieldEmail := FieldEmail(str)
  return &fieldEmail
}

func checkValidators(validators ...validator) error {
  for _, v := range validators {
    if v == nil {
      continue
    }
    if err := v.Validate(); err != nil {
      return err
    }
  }
  return nil
}

func main() {
  fmt.Printf("Error: %v\n", checkValidators(NewFieldEmail("[email protected]")))

  var email *FieldEmail
  fmt.Printf("Error: %v\n", checkValidators(email))
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question