tgoop.com/golangtests/773
Create:
Last Update:
Last Update:
🐹 Задача с подвохом: Generics и интерфейсы (Go 1.24)
Условие:
Что выведет следующий код и почему?
package main
import (
"fmt"
)
type Stringer interface {
String() string
}
type MyInt int
func (m MyInt) String() string {
return fmt.Sprintf("MyInt: %d", m)
}
func printValue[T any](val T) {
var s Stringer
if v, ok := any(val).(Stringer); ok {
s = v
}
if s != nil {
fmt.Println("Stringer:", s.String())
} else {
fmt.Println("Default:", val)
}
}
func main() {
var x MyInt = 5
printValue(x)
printValue(10)
}
❓ Вопрос:
Что будет напечатано? Почему результат может удивить даже опытных Go-разработчиков?
🔍 Разбор:
Этот код использует generics и проверяет, реализует ли
val
Stringer
Пошагово:
1️⃣
var x MyInt = 5
Тип
MyInt
Stringer
```go
func (m MyInt) String() string { ... }
```
2️⃣
printValue(x)
-
val
MyInt
- В строке:
any(val).(Stringer)
- Приведение типа успешно, потому что
MyInt
Stringer
- Печатается:
```
Stringer: MyInt: 5
```
3️⃣
printValue(10)
- Тип
val
int
-
int
Stringer
- Приведение
any(val).(Stringer)
- Печатается:
```
Default: 10
```
✅ Ожидаемый вывод:
```
Stringer: MyInt: 5
Default: 10
```
💥 Подвох:
- Даже если
MyInt
int
String()
- Многие забывают, что встроенные типы (int, string, и т.д.) никогда не реализуют интерфейсы напрямую, даже если они похожи на пользовательские типы.
- Ключевой момент:
any(val)
🆕 Почему это актуально для Go 1.24:
Generics в Go 1.22+ улучшились по типовой проверке и стали более гибкими. Go 1.24 сделал generics более стабильными и оптимизированными, но все еще важно понимать различия между типами и интерфейсами, особенно при работе с
any
🛡️ Лайфхак:
Если вы хотите печатать всё одинаково для типов с
String()
```go
func printValue2[T fmt.Stringer](val T) {
fmt.Println("Stringer (generic):", val.String())
}
```
✅ Вывод:
Generics упрощают код, но внимательность к типам и их интерфейсам критически важна. Даже небольшие различия между
int
MyInt
BY Go tests
Share with your friend now:
tgoop.com/golangtests/773