GOLANGTESTS Telegram 773
🐹 Задача с подвохом: 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) не срабатывает (ok == false).
- Печатается:
```
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(), можно сделать generic-констрейн с интерфейсом:

```go
func printValue2[T fmt.Stringer](val T) {
fmt.Println("Stringer (generic):", val.String())
}
```

Вывод:

Generics упрощают код, но внимательность к типам и их интерфейсам критически важна. Даже небольшие различия между
int и MyInt влияют на поведение программы.



tgoop.com/golangtests/773
Create:
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) не срабатывает (ok == false).
- Печатается:
```
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(), можно сделать generic-констрейн с интерфейсом:

```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

View MORE
Open in Telegram


Telegram News

Date: |

Matt Hussey, editorial director at NEAR Protocol also responded to this news with “#meIRL”. Just as you search “Bear Market Screaming” in Telegram, you will see a Pepe frog yelling as the group’s featured image. "Doxxing content is forbidden on Telegram and our moderators routinely remove such content from around the world," said a spokesman for the messaging app, Remi Vaughn. SUCK Channel Telegram fire bomb molotov November 18 Dylan Hollingsworth yau ma tei A new window will come up. Enter your channel name and bio. (See the character limits above.) Click “Create.”
from us


Telegram Go tests
FROM American