Как в go вернуть значение функции если результат выполнения имеет разные типы?
Пишу функцию, которая обрабатывает букву Z: она преобразует её в "зет", если Z используется как самостоятельное слово, или в "з", если она входит в состав слова.
Перед обработкой буквы применяется функция, которая заменяет буквосочетания, например "sh" -> "ш" и подобные. Поэтому для обработки я использую руны вместо строк (это позволяет более корректно интерпретировать байты). Как возвращать из функции одно из возможных значений — руну ИЛИ массив рун?
Исходный код:
func Zhandler(a string, i int) (rune || []rune) {
if i == 0 && utf8.RuneCountInString(a) == 1 {
return []rune{'з', 'э', 'т'}
}
return 'з'
}
Ответы (1 шт):
Golang - язык со строгой типизацией, и полиморфизм возможен лишь для интерфейсов: если типы А и В реализуют общий интерфейс I, то функция, возвращающая I, может вернуть как объект типа A, так и объект типа B.
rune и []rune - это базовые типы, которые не реализуют никаких интерфейсов, поэтому у них нет общего типа.
Есть много вариантов, как полиморфизм симулировать.
Например, можно возвращать два значения:
func Zhandler(a string, i int) (rune, []rune) {
if i == 0 && utf8.RuneCountInString(a) == 1 {
return 0, []rune{'з', 'э', 'т'}
}
return 'з', nil
}
В вызывающей стороне достаточно проверить, равно ли второе возвращаемое значение nil
func main() {
z, zet := Zhandler("test", 0)
if zet == nil {
fmt.Println("одна буква Зэ: ", z)
} else {
fmt.Println("Зэт: ", zet)
}
}
Можно сделать структуру ZhandlerReturn
type ZhandlerReturn struct {
Z rune
Zet []rune
}
func Z() ZhandlerReturn {
return ZhandlerReturn{
Z: 'з',
Zet: nil,
}
}
func Zet() ZhandlerReturn {
return ZhandlerReturn{
Z: 0,
Zet: []rune{'з', 'э', 'т'},
}
}
func (zh ZhandlerReturn) IsZ() bool {
return zh.Zet == nil
}
func Zhandler2(a string, i int) ZhandlerReturn {
if i == 0 && utf8.RuneCountInString(a) == 1 {
return Zet()
}
return Z()
}
Но, если честно, зачем вам отдельная руна? Потом ведь наверняка придётся объединять результат с другими рунными массивами? Поэтому возвращайте в обоих случаях массивы:
var (
ZE = []rune("з")
ZET = []rune("зэт")
)
func Zhandler3(a string, i int) []rune {
if i == 0 && utf8.RuneCountInString(a) == 1 {
return ZET
}
return ZE
}