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-констрейн с интерфейсом:
Generics упрощают код, но внимательность к типам и их интерфейсам критически важна. Даже небольшие различия между int и MyInt влияют на поведение программы.
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-констрейн с интерфейсом:
Generics упрощают код, но внимательность к типам и их интерфейсам критически важна. Даже небольшие различия между int и MyInt влияют на поведение программы.
BY Go tests
Warning: Undefined variable $i in /var/www/tg-me/post.php on line 283
Telegram and Signal Havens for Right-Wing Extremists
Since the violent storming of Capitol Hill and subsequent ban of former U.S. President Donald Trump from Facebook and Twitter, the removal of Parler from Amazon’s servers, and the de-platforming of incendiary right-wing content, messaging services Telegram and Signal have seen a deluge of new users. In January alone, Telegram reported 90 million new accounts. Its founder, Pavel Durov, described this as “the largest digital migration in human history.” Signal reportedly doubled its user base to 40 million people and became the most downloaded app in 70 countries. The two services rely on encryption to protect the privacy of user communication, which has made them popular with protesters seeking to conceal their identities against repressive governments in places like Belarus, Hong Kong, and Iran. But the same encryption technology has also made them a favored communication tool for criminals and terrorist groups, including al Qaeda and the Islamic State.
How to Buy Bitcoin?
Most people buy Bitcoin via exchanges, such as Coinbase. Exchanges allow you to buy, sell and hold cryptocurrency, and setting up an account is similar to opening a brokerage account—you’ll need to verify your identity and provide some kind of funding source, such as a bank account or debit card. Major exchanges include Coinbase, Kraken, and Gemini. You can also buy Bitcoin at a broker like Robinhood. Regardless of where you buy your Bitcoin, you’ll need a digital wallet in which to store it. This might be what’s called a hot wallet or a cold wallet. A hot wallet (also called an online wallet) is stored by an exchange or a provider in the cloud. Providers of online wallets include Exodus, Electrum and Mycelium. A cold wallet (or mobile wallet) is an offline device used to store Bitcoin and is not connected to the Internet. Some mobile wallet options include Trezor and Ledger.