Какие ключевые особенности языка Go и их аналоги в Java?

«Какие ключевые особенности языка Go и их аналоги в Java?» — вопрос из категории Other, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Go и Java имеют разную философию дизайна. Вот ключевые особенности Go и их приблизительные аналоги/концепции в Java:

Особенность Go Концепция/Аналог в Java Комментарий
Горутины (goroutines) Виртуальные потоки (java.lang.VirtualThread, Java 21+) Легковесные потоки, управляемые рантаймом Go. В Java 21+ VirtualThread предлагает схожую модель для масштабируемой конкурентности. До Java 21: Классические Thread гораздо тяжелее.
Каналы (channels) java.util.concurrent.BlockingQueue (напр., LinkedBlockingQueue) Каналы Go — примитив синхронизации «из коробки». В Java для передачи данных между потоками часто используют очереди.
select по каналам java.nio.channels.Selector (для I/O) или CompletableFuture.anyOf() Механизм мультиплексирования операций. В Java Selector используется для асинхронного I/O, а не для общих структур данных.
Структурная типизация интерфейсов Нет прямого аналога В Go тип реализует интерфейс неявно, если имеет нужные методы. В Java требуется явное объявление implements.
Отсутствие классического ООП (наследования) Композиция и интерфейсы Go поощряет композицию. В Java также рекомендуется composition over inheritance.
Указатели (с арифметикой) Ссылки, но без арифметики Java не предоставляет доступа к raw-памяти и арифметики указателей для безопасности.
Встроенная сборка мусора Есть (JVM) Оба языка имеют GC, но алгоритмы и настройки различаются.
Статическая линковка, один бинарник JAR-файл + JVM Go компилируется в статически линкованный исполняемый файл. Java компилируется в байт-код, требующий JVM.

Пример конкурентности:

// Java 21+: Виртуальный поток (аналог горутины)
Thread.startVirtualThread(() -> {
    System.out.println("Hello from virtual thread");
});

// Использование BlockingQueue как канала
BlockingQueue<String> ch = new LinkedBlockingQueue<>();
// Поток-писатель
new Thread(() -> {
    try { ch.put("message"); } catch (InterruptedException e) {}
}).start();
// Поток-читатель
new Thread(() -> {
    try { String msg = ch.take(); } catch (InterruptedException e) {}
}).start();

Основное отличие: Go спроектирован для простоты и эффективной конкурентности на уровне языка, в то время как Java предоставляет богатую экосистему и мощную виртуальную машину, с развитой конкурентностью в стандартной библиотеке (java.util.concurrent).