Как проверить 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("test@test")))

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


T.к. *FieldEmail на самом деле является полем структуры и таких полей много, не хочется каждое поле проверять на != nil до передачи в функцию checkValidators().


Решение, которое я нашел, использует рефлексию, чего тоже бы хотелось избежать.

Код на playground

Есть какие-то идеи, как еще это можно реализовать?
  • Вопрос задан
  • 188 просмотров
Решения вопроса 1
Можно например так:
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("test@test")))

	var email *FieldEmail
	fmt.Printf("Error: %v\n", checkValidators(email))
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы