Форум программистов, компьютерный форум, киберфорум
Go (Golang)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
2 / 2 / 0
Регистрация: 04.05.2010
Сообщений: 93

Аналог getch() в golang

21.04.2025, 02:07. Показов 4725. Ответов 40
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Нужна возможность для консольной проги прерывать исполнение, пока не брякну по клаве, и потом чтоб исполнение продолжилось. Т.е. нужен аналог getch()

пока пользуюсь
Go
1
2
reader := bufio.NewReader(os.Stdin)
_, _, _ = reader.ReadRune()
но это неудобно, т.к. надо обязательно прожать ввод
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.04.2025, 02:07
Ответы с готовыми решениями:

Аналог fgets для Golang
Собственно, есть ли какой-либо аналог сишной функции fgets в Golang? В своём консольном приложении...

Создание форм в Golang?
Доброго времени суток! Интересует создание форм в Go. Есть какой то редактор форм в IDE для Go?...

Web сервис на Golang + martini
Добрый день, уважаемые форумчани. Есть у кого готовые исходники разработанного Web сервиса или...

40
Эксперт JS
 Аватар для DrType
6553 / 3624 / 1075
Регистрация: 07.09.2019
Сообщений: 5,877
Записей в блоге: 1
23.04.2025, 12:58
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от abit Посмотреть сообщение
там это повсюду
Не спорю, мой вброс был именно про код проекта - не библиотеки (и не фреймворка). Здесь приоритет в удобстве отладки, а в библиотечных функциях наверное в чем-то другом.
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
23.04.2025, 21:25
Цитата Сообщение от abit Посмотреть сообщение
обе функции вернут одно и тоже, а если нет разницы, зачем писать больше?
Go
1
2
3
4
5
6
7
func readFile() ([]byte, error) {
    data, err := os.ReadFile("file.txt")
    if err != nil {
        return nil, fmt.Errorf("read file: %w", err)
    }
    return data, nil
}
Теперь то же самое с вопросиком на Rust, будьте добры.
0
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,882
23.04.2025, 22:00
korvin_, ну там есть два пути, из коробки
Rust
1
2
3
4
fn read_file() -> Result<Vec<u8>, Error> {
    let data = fs::read("file.txt").map_err(|e| format!("Не удалось прочитать файл: {}", e))?;
    Ok(data)
}
Или подключить крейты в cargo anyhow для отладки без драмы, или аж совсем серьёзно нужно следить - thiserror, если прям интересно, могу скинуть запись вебинара по обработке ошибок, там рассказывали варианты Си, C++, Java, Haskell, Go и Rust, сравните сами подходы) только у некоторых после просмотра палец дёргается при виде поисковой строки писать install rust, так что это не для слабых духом
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
23.04.2025, 22:07
Цитата Сообщение от abit Посмотреть сообщение
Rust
1
let data = fs::read("file.txt").map_err(|e| format!("Не удалось прочитать файл: {}", e))?;
И вот вся простота куда-то улетучилась.

Цитата Сообщение от abit Посмотреть сообщение
Или подключить крейты в cargo anyhow для отладки без драмы
Не надо, речь не про отладку.

Цитата Сообщение от abit Посмотреть сообщение
или аж совсем серьёзно нужно следить - thiserror
Не знаю, что значит "следить".

Цитата Сообщение от abit Посмотреть сообщение
только у некоторых после просмотра палец дёргается при виде поисковой строки писать install rust
Это к доктору.
0
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,882
23.04.2025, 22:14
в anyhow грубо говоря ты можешь подцеплять конткест каждый раз
Rust
1
2
3
4
pub fn read_file() -> Result<Vec<u8>> {
    fs::read("file.txt")
        .context("read file")
}
всё... вот простота и вернулась)
в thiserror функционал, что Go даже не снилось
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
23.04.2025, 23:10
Цитата Сообщение от abit Посмотреть сообщение
всё... вот простота и вернулась)
Мне не нужно просто "подцеплять контекст".

Цитата Сообщение от abit Посмотреть сообщение
в thiserror функционал, что Go даже не снилось
Мне не нужен какой-то абстрактный "функционал обработки ошибок".
0
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,882
23.04.2025, 23:36
разберитесь что вам надо, потом только приступайте нажимать кнопки на клавиатуре
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
23.04.2025, 23:40
Цитата Сообщение от abit Посмотреть сообщение
разберитесь что вам надо, потом только приступайте нажимать кнопки на клавиатуре
Я-то разобрался. Вот вам пример посложнее и попрактичней, чтобы тоже смогли разобраться:

Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
func (svc *SomeService) Handle(req *Request) (_ *Response, err error) {
    var key  = svc.dataKey(req)
    var data *domain.Data
 
    data, err = svc.cache.getData(key)
    
    if err == nil {
        return svc.responseOK(data), nil
    }
    
    if !errors.Is(err, cache.ErrEmpty) {
        svc.log.Error("Cache unavailable", err)
        // ignore err
    }
 
    data, err = svc.db.getData(key)
    
    if errors.Is(err, db.ErrNotFound) {
        svc.log.Warn("Data not found", log.Int64("user_id", req.UserID))
        return svc.responseNotFound(key), nil
    }
    
    if err != nil {
        svc.log.Error("Database unavailable", err, log.Int64("user_id", req.UserID))
        return nil, err
    }
    
    if err = svc.cache.putData(key, data); err != nil {
        svc.log.Error("Cache unavailable", err)
        // ignore err
    }
    
    return svc.responseOK(data), nil
}
0
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,882
24.04.2025, 00:01
Go
1
2
3
4
5
6
7
func readFile() ([]byte, error) {
    data, err := os.ReadFile("file.txt")
    if err != nil {
        return nil, fmt.Errorf("read file: %w", err)
    }
    return data, nil
}
этот код
и этот
Rust
1
2
3
4
pub fn read_file() -> Result<Vec<u8>> {
    fs::read("file.txt")
        .context("read file")
}
делают одно и тоже, если вы этого не понимаете, то чего мы обсуждаем
Цитата Сообщение от korvin_ Посмотреть сообщение
Вот вам пример посложнее и попрактичней:
откуда здесь логирование всплыло, это вообще в другом слое должно быть, оно к теме не имеет отношения, это код не попрактичней, а просто винегрет, который мне было бы даже стыдно людям показывать

Go
1
2
3
4
if !errors.Is(err, cache.ErrEmpty) {
    svc.log.Error("Cache unavailable", err)
    // ignore err
}
а если ошибка кэша не ErrEmpty? работаем? замечательно, а что БД то не у нас крутится дома, пусть пыхтит...

Go
1
2
3
4
if err = svc.cache.putData(key, data); err != nil {
    svc.log.Error("Cache unavailable", err)
    // ignore err
}
та же шляпа, а что можно и заведомо старые данные из кэша жрать

Go
1
func (svc *SomeService) Handle(req *Request) (_ *Response, err error)
чем это отличается от
Go
1
func (svc *SomeService) Handle(req *Request) (*Response, error)
? посолидней выглядит?

Go
1
2
3
data, err = svc.db.getData(key)
    
    if errors.Is(err, db.ErrNotFound) {
не проверили же err != nil перед errors.Is, а вдруг там не nil уже?

Go
1
return nil, err
замечательно, а обернуть, как потом диагностировать где и почему?

я такое на Rust писать не буду, да и не позволит он такое г-цо скомпилировать
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
24.04.2025, 00:50
Цитата Сообщение от abit Посмотреть сообщение
откуда здесь логирование всплыло
Гм, помогает расширить понимание примера.

Цитата Сообщение от abit Посмотреть сообщение
это вообще в другом слое должно быть
С чего вы взяли? Впрочем, покажите, как логировать в другом слое, не выходя из функции.

Цитата Сообщение от abit Посмотреть сообщение
оно к теме не имеет отношения
Прямое отношение. Это достаточно реалистичный пример кода на Go с обработкой ошибок.

Цитата Сообщение от abit Посмотреть сообщение
это код не попрактичней, а просто винегрет, который мне было бы даже стыдно людям показывать
Здесь нет ни грамма винегрета, прямой, линейный, понятный код, который делает ровно то, что написано. Легко читать, легко понимать, легко сопровождать.

Цитата Сообщение от abit Посмотреть сообщение
а если ошибка кэша не ErrEmpty?
Это и есть проверка, что ошибка не ErrEmpty. Символ ! (восклицательный знак) -- это унарный оператор not, типичный для языков с Си-подобной лексикой.

Цитата Сообщение от abit Посмотреть сообщение
замечательно, а что БД то не у нас крутится дома, пусть пыхтит...
Не у нас. А что вы предлагаете делать при ошибке доступа к кэшу? Вернуть пользователю ошибку вместо данных из базы? Крайне сомнительное решение.

Цитата Сообщение от abit Посмотреть сообщение
та же шляпа, а что можно и заведомо старые данные из кэша жрать
Какое отношение устаревание кэша имеет к операции записи в кэш только что считанных, актуальных данных из БД?
Какое отношение актуализация кэша имеет к обработке запроса на чтение данных?

Цитата Сообщение от abit Посмотреть сообщение
посолидней выглядит?
Объявляет переменную err.

Цитата Сообщение от abit Посмотреть сообщение
не проверили же err != nil перед errors.Is, а вдруг там не nil уже?
Что? Зачем проверять err != nil перед errors.Is?

Цитата Сообщение от abit Посмотреть сообщение
амечательно, а обернуть, как потом диагностировать где и почему?
Где и почему что смотреть в логе.

Цитата Сообщение от abit Посмотреть сообщение
я такое на Rust писать не буду, да и не позволит он такое скомпилировать
Ясно-понятно. Как только доходит до дела, Rust оказывается не способен.
0
Эксперт .NET
 Аватар для Usaga
14726 / 9496 / 1362
Регистрация: 21.01.2016
Сообщений: 35,807
25.04.2025, 16:36
Цитата Сообщение от abit Посмотреть сообщение
лично да, конкретно с C#
смотри, дело было так, было, проект был не мой, сразу говорю, может нюансы его реализации не все понимал, но когда я написал его с нуля на fpc, проблема ушла сразу.
там было несколько плат (до 32), у каждой свой IP, зависит от объекта если память не изменяет конкретно на том было в сумме 18, 12 одного типа и 5-6 другого, с общим интерфейсом, для каждого запускался свой поток со своим сокетом, но немного разного назначения, суть работы с ними была такая отправляешь им команду (tcp 100мб/с), длина пакета не большая, в среднем не более 10 байт (но бывают исключения) типа
S3 - установи конечному автомату состояние 3
P114.23 T77 - установи значение ожидаемого тока в 114.23мА и время запуска 77мс
вот такого плана команды, никаких длинных посылок, в ответ на любую команду приходило полное состояние в виде
S7 A0 B001 P113.11 ... и т.д., ответ всегда примерно одинаковой длины около 50 байт, ну там +/- 3 байта, по нему можно понять что там происходит, вроде не такой большой траффик, приходил ответ не позднее чем через 100мс после запроса, по ответу нужно было понять принялась ли команда, и прочее, всё работало, пока не наткнулись на противоречие, там некоторые устройства зависели от других, в плане если на устройстве A (одного типа) какой-то датчик сработал (это было поле типа DFF, в Hex формате приходило состояние датчиков после D), то другому устройству B (плата другого типа) нужно было передать что теперь ток в 100 раз меньше/больше, грубо говоря переключить шкалу, иначе на приборе оно зашкаливало и стрелка резко дёргалась, однако ты не имеешь права посылать команду на B, пока не пришёл ответ от неё, поэтому возникал момент, что приходит команда на смену тока от А, а миллисекундой раньше ушёл запрос на B, дожидались ответа и только после этого отправляли на B, время реакции было больше 100мс, решили ну типа давайте отправлять команды на B только после ответа А, но при этом нужно чтобы команды на B всё таки уходили, вдруг оператор чего то другое изменит, поэтому на B отправляли новые если от последнего ответа A прошло меньше 10мс, скомкано объяснил, в общем по факту, профилируя выяснили что программа отвлекается именно на GC и иногда, нет-нет а стрелка дёргается, в среднем 2-3 раза в минуту, что ужасно бесило операторов за дорогущим оборудованием.
там команда C#-ников с этим пару месяцев возилась, позвали меня, я не стал возиться с их кодом на C# больше одного вечера, написал им либу для работы с платами на fpc со всеми платами сразу ровно по той же логике за пару дней (так же запускает до 32 потоков и обрабатывает их в той же логике), они просто подключили .dll к своему проекту, и ни одного дёргания стрелки не было
Ну так у тебя тут строгие привязки ко времени реакции. Это real time. Я уже выше писал, что это не подходящая задача для управляемого языка.

Как будто нет противоречий.
0
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,882
26.04.2025, 01:37
Цитата Сообщение от korvin_ Посмотреть сообщение
С чего вы взяли? Впрочем, покажите, как логировать в другом слое, не выходя из функции.
вы знаете что такое чистая архитектура? надеюсь хоть слышали, так вот логирование это вообще не тот слой, подскажу - нужно логирвать слоем выше - интерфейса или инфраструктуры, можно сквозным ещё, твоё апи вообще не должно знать что там снаружи
Цитата Сообщение от korvin_ Посмотреть сообщение
Прямое отношение. Это достаточно реалистичный пример кода на Go с обработкой ошибок.
Логирование не может быть обработкой ошибок, вы ерунду пишите
мне правда лень даже разбирать эту чушь дальше, рекомендую почитать вам книжки сперва
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
26.04.2025, 10:37
Цитата Сообщение от abit Посмотреть сообщение
вы знаете что такое чистая архитектура? надеюсь хоть слышали, так вот логирование это вообще не тот слой, подскажу - нужно логирвать слоем выше - интерфейса или инфраструктуры, можно сквозным ещё, твоё апи вообще не должно знать что там снаружи
Где вы увидели "слой интерфейса или инфраструктуры"?

Цитата Сообщение от abit Посмотреть сообщение
Логирование не может быть обработкой ошибок, вы ерунду пишите
мне правда лень даже разбирать эту чушь дальше, рекомендую почитать вам книжки сперва
Вы кроме чтения книжек, чем-нибудь практичным занимались? Рекомендую поднабраться опыта, расширить кругозор, потом про книжки рассказывать.

Добавлено через 19 минут
Вот вам ситуация: сделали вы своё "логгирование слоем выше", выстроили иерархию классов ошибок, чтобы они логгировались разными уровнями, всё такое.

1) Расскажите, как DEBUG/INFO логи будете вести? Тоже через ошибки?

2) Возникла необходимости определённую ошибку в одном месте логгировать, в другом -- нет. Как вы их отличите на своём "слое выше"? Сделаете два разных класса для одной и той же ошибки, и по-разному будете их обрабатывать в слое выше? Теперь в третьем месте нужно ошибку логировать, но другим уровнем (например, не ERROR, а WARN). И вот вы вместо того, чтобы решать бизнес-задачу, пердолите свою развесистую иерархию ошибок, делаете очередной error-handling framework, который никакую проблему не решает, но время на себя забирает.

Добавлено через 8 минут
И вы так и не ответили:

Как мне логировать уровнем выше ошибки, которые не приводят к выходу из метода на текущем уровне?
0
47 / 39 / 10
Регистрация: 25.02.2025
Сообщений: 84
26.04.2025, 16:18
В книжках пишут что ошибки надо либо журналировать (то есть обрабатывать) либо передавать на уровень выше (возвращать из процедуры). Вроде бы разумно.
1
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,882
02.05.2025, 01:12
Цитата Сообщение от NotAbug Посмотреть сообщение
В книжках пишут что ошибки надо либо журналировать (то есть обрабатывать) либо передавать на уровень выше (возвращать из процедуры). Вроде бы разумно.
всё верно пишут, не слушайте бредятину выше про логирование на ошибке, это колхоз
логирование и ошибка это разные слои архитектуры, чтобы ты всегда мог переключить логер хоть в файл, хоть в БД, хоть на телефон соседки по даче
человек, видимо, решил что если написал пару приложений, то он практик и теория уже не нужна, он лучше знает, я таких много повидал) никто из них не стал выше мидла
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
02.05.2025, 11:29
abit, вы видимо не в курсе, что библиотеки логирования элементарно переключаются куда надо и вообще всячески настраиваются в конфиг-файле, без всяких манипуляций в коде. Кроме того, вы, похоже не в курсе, как осуществляется сбор логов в микросервисах, иначе бы не писали про файлы, БД и телефоны.

Вы видимо начитались «умных» книжек, но кругозор на них и закончился.
1
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,882
03.05.2025, 05:46
korvin_,
странные вы какие-то мы обсуждали спецификацию ошибок, а что с ними делать - никак не относится к этой спецификации, как работать с этими ошибками - это вообще про другое, что мы хотим - печатать ошибки, логировать, слать метрику в prometheus, кидать в sentry какую-то ошибку - это у нас принято вообще другими крейтами делать, прямо есть крейт для логирования, есть для prometheus, есть для sentry, они вообще никак не завязаны с anyhow или thiserror, тут же в коде просто каша и только на словах вы всегда можете переключить логер, а на деле если код достаточно большой, то ой как намучаетесь

да даже не хочу приводить примеры и продолжать рассказывать очевидные вещи, понятно, что у вас просто опыта в больших проектах нет, закроем тему, может со временем доверят вам какой-то серьёзный прод и вы поймете о чём речь
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
03.05.2025, 11:55
Понималка у вас оставляет желать лучшего. А мы прекрасно переключаем uber zap logger конфигом в зависимости от окружения.
0
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,882
04.05.2025, 22:16
Цитата Сообщение от korvin_ Посмотреть сообщение
А мы прекрасно переключаем uber zap logger конфигом в зависимости от окружения.
ой, вы это кто? ты и твоя кошка?
ладно, своего нет, тебе, очевидно ничего серьёзного не доверят, кинь ссылку на чужой проект выше 10000 строк, где используется логирование прям по месту ошибки

Rust не позволяет игнорировать ошибки — ты обязан их обрабатывать!
а эту чушь из go, ну типа ошибка кэша бд, и фиг с ним, продолжим! засунь в свои тихие игры под боком у спящих людей, и никому не рассказывай

Кликните здесь для просмотра всего текста

наверное ты не поймешь отсылку, что думают системные программисты про программистов на Golang, поэтому намекну


0
Эксперт .NET
 Аватар для Usaga
14726 / 9496 / 1362
Регистрация: 21.01.2016
Сообщений: 35,807
05.05.2025, 06:10
Цитата Сообщение от abit Посмотреть сообщение
а эту чушь из go, ну типа ошибка кэша бд, и фиг с ним, продолжим!
Что-то я не очень понимаю чем тут go отличается от других языков. В других языках ошибку можно перехватить и проигнорить... Всё в разработчика упирается...

Цитата Сообщение от abit Посмотреть сообщение
наверное ты не поймешь отсылку, что думают системные программисты про программистов на Golang, поэтому намекну
Интересно, а зачем надо спрашивать мнение системных программистов о языке не для системной разработки? Оно будет какой-то вес иметь?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
05.05.2025, 06:10

Golang пройтись по массиву в шаблоне
код go: func TakeToRepair(w http.ResponseWriter, rnd render.Render) { // rnd.HTML(200,...

Golang postgres проверить если запрос не вернул записей
Есть такой код: func ModelLoginAuth(id, pwd string) (*MedReg) { //Cписок мед регистраторов ...

Golang Modbus TCP Server
Здравствуйте. Подскажите как реализовать модбас сервер. нашел в интернете примеры, но вот не пойму...

Golang - WiringPi на Orange pi zero
Здравствуйте. пытаюсь по работать с портами ввода вывода на orange pi, но не получается установить...

Файловый веб-сервер на golang
собственно вот пример простой, работает хорошо package main; import ( &quot;http&quot; &quot;fmt&quot; ) ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru