Написание функции дженериков без дженериков
Я знаю, что Go не будет иметь генериков в будущем, и есть рекомендации по их замене другими конструкциями. Но с моим примером ниже я застрял.
func P(any interface{}, err error) (interface{}) {
if err != nil {
panic("error: "+ err.Error())
}
return any
}
Как вы могли догадаться, я пытаюсь просто терпеть неудачу при любой ошибке и хочу поместить P()
только в любую функцию, возвращающую два результата, а вторая - ошибку. Это нормально работает, но any
теряет информацию о типе и является лишь пустым интерфейсом в результате.
Поскольку я также вызываю функции lib, я не вижу способа решить эту проблему с помощью интерфейсов или отражений.
Любые идеи? Я полностью на неправильном пути или близка к цели?
Ответы
Ответ 1
Одним из решений будет go generate
ваша функция P()
, по одному для каждого конкретного типа, с которым вам нужно работать.
См. Примеры в:
Это упростило бы обращение к этим функциям lib, поскольку созданные конкретные реализации P() использовали бы правильный тип вместо интерфейса {}.
Ответ 2
То, что вы хотите сделать, потребует дженериков, но, как вы уже упоминали, Go не поддерживает общие типы. Поэтому вы не можете создать общую функцию, которая не потеряет тип.
Вам нужно создать такую функцию для каждого типа, который вы хотите поддерживать. Обратите внимание: стандартная библиотека уже содержит некоторые из них, идущие под названием MustXXX()
, которые вы можете использовать из коробки, например:
template.Must(t *Template, err error) *Template
Или "похожие" функции, которые подавляют error
, но если все еще происходит, паники, например:
regexp.MustCompile(str string) *Regexp
(подавляет error
, но паники, если str
не является допустимым регулярным выражением)
Ответ 3
Если вы планируете просто впадать в ошибки (плохую идею) или записывать их в журнал, просто определите функцию для этого и используйте ее. Например.
func checkErr(err error) {
if err != nil {
log.Println(err)
}
}
// ...
func foo() {
a, err := doA()
checkErr(err)
b, err := doB()
checkErr(err)
// etc.
}
Пользователь twotwotw уже связан с Ошибки являются значениями", в котором показаны дополнительные примеры того, как сделать обработку ошибок менее повторяющейся. Но я бы рекомендовал просто написать целую вещь if err != nil
, потому что по моему опыту каждая третья ошибка, если не вторая, требует некоторой дополнительной обработки.