• Стоит ли начинать учить программирование с Golang?

    Maksim_64
    @Maksim_64
    Data Analyst
    1. Начинать с go не нужно. Это довольно нишевый язык, по которому будет крайне тяжело найти первую работу. Обычно go специалисты, это программисты с опытом которые в определенный момент добавляют его в свое портфолио.

    2. Платные курсы тоже не нужно, стоят они не дешево и это плохая инвестиция денег, учись бесплатно, а денежки пусть будут.

    В остальном определись не с языком, а что ты именно хочешь делать, в создании какого продукта принимать участие и под это дело подбирай язык, и не пытайся быть особенным, тебе нужен большой рынок и скромненькое местечко на этом рынке.
    Ответ написан
    4 комментария
  • Знаю только Python и SQL. Нужно ли наращивать стек знаний перед попыткой смены работы?

    vabka
    @vabka
    Токсичный шарпист
    Перед сменой работы следует сначала пройти собеседование и получить оффер, иначе рискуешь остаться и без воробья и без журавля.

    или мне в настоящее время стоит относить себя к т. н. «Разработчикам приложений» (по классификации «Хабр Карьеры»)

    То что ты описываешь - похоже на бэкендера.

    Нужны ли на рынке труда специалисты с таким стеком за такую зарплату

    Вопрос не имеет смысла, ибо он не отвечает на главный вопрос - найдёт ли конкретный соискатель себе рабочее место.
    надо заняться самообразованием, изучая, скажем связку FastAPI + Kafka + Kubernetes?

    Самообразование никогда лишним не будет.
    Ответ написан
    Комментировать
  • Где умные указатели размещают полученные данные?

    vabka
    @vabka
    Токсичный шарпист
    Cell<T> has the same memory layout and caveats as UnsafeCell<T>. In particular, this means that Cell<T>has the same in-memory representation as its inner type T.


    У остальных нет никаких обязательств о memory representation, но они тоже ничего в куче не выделяют.

    Ну и всегда можно посмотреть на исходники)
    https://doc.rust-lang.org/src/core/cell.rs.html#293
    https://doc.rust-lang.org/src/core/cell.rs.html#2034
    https://doc.rust-lang.org/src/core/cell.rs.html#700
    https://doc.rust-lang.org/src/core/cell/once.rs.html#33
    Ответ написан
    Комментировать
  • Выражение без эффекта перемещает переменную?

    @deliro
    Если bb; убрать, то всё работает, почему так? Никакого перемещения там не происходит, но компилятор думает иначе.

    Перемещение происходит. Семантически это выражение эквивалентно `{ bb }`

    Это точно системный язык на котором можно писать серьёзные вещи?

    Нет, язык херня. Беги писать на жс

    Или тут и правда происходит некое перемещение в параллельную вселенную?

    Хорошая привычка — агриться на вещи, которые ты не понимаешь. Далеко пойдёшь.
    Ответ написан
    3 комментария
  • Как работает этот код?

    bingo347
    @bingo347
    Crazy on performance...
    Очень упрощенно HashMap можно представить следующим образом:
    pub struct HashMap<K, V> {
        table: Table<(K, V)>,
    }
    
    struct Table<T> {
        // битовая маска занятых ячеек в items
        mask: u64,
        items: Box<[std::mem::MaybeUninit<Item<T>>; 64]>,
        len: usize,
    }
    
    struct Item<T> {
        data: T,
        next: Option<std::ptr::NonNull<Item<T>>>,
    }


    А Entry так:
    pub enum Entry<'a, K, V> {
        Vacant(VacantEntry<'a, K, V>),
        Occupied(OccupiedEntry<'a, K, V>),
    }
    
    pub struct VacantEntry<'a, K, V> {
        hash: u64,
        key: K,
        table: &'a mut Table<(K, V)>,
    }
    
    pub struct OccupiedEntry<'a, K, V> {
        elem: Bucket<(K, V)>,
        table: &'a mut Table<(K, V)>,
    }
    
    // указатель на Item.data
    struct Bucket<T> {
        ptr: std::ptr::NonNull<T>,
    }


    Как можно заметить у Entry есть лайфтайм, который связывает его с HashMap от которой он создан. А внутри есть мутабельная ссылка с этим лайфтаймом на таблицу с данными HashMap.
    Метод entry упрощенно выглядит примерно так:
    impl<K, V> HashMap<K, V> {
        pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V>
        where
            K: Eq + std::hash::Hash,
        {
            use std::hash::Hasher as _;
            let mut hasher = self.get_hasher();
            key.hash(&mut hasher);
            let hash = hasher.finish();
    
            if let Some(elem) = self.table.find(hash, |(k, _)| key == *k) {
                Entry::Occupied(OccupiedEntry {
                    elem,
                    table: &mut self.table,
                })
            } else {
                Entry::Vacant(VacantEntry {
                    hash,
                    key,
                    table: &mut self.table,
                })
            }
        }
    
        fn get_hasher(&self) -> impl std::hash::Hasher {
            todo!()
        }
    }
    
    impl<T> Table<T> {
        fn find(&self, hash: u64, is_match: impl FnMut(&T) -> bool) -> Option<Bucket<T>> {
            todo!()
        }
    }

    Как видим мутабельная ссылка всё же есть, только она завернута в структуру, так как одной этой ссылки не достаточно, так как в случае свободной Entry нам нужно хранить ещё и ключ, а заодно и хэш (чтоб не считать его снова), а в случае занятой - указатель на бакет (область памяти где храниться пара ключ и значение).
    Ответ написан
    Комментировать
  • Может ли приложение слушать несколько портов?

    saboteur_kiev
    @saboteur_kiev Куратор тега Компьютерные сети
    software engineer
    Приложение может слушать сколько угодно портов.
    Можно даже один порт слушать двумя приложениями, есть даже такой вариант, но он редко используется.

    Но вот совершенно не обязательно разбивать листенеры по ядрам - в большинстве случаев, если у вас предполагается нагрузка, то после того, как на порт приходят данные, проверяется есть ли уже установленная сессия, и если нет, создается отдельный поток для нового юзера/подключения. А уже какое ядро - ОС сама разберется с многопоточностью.
    Ответ написан
    2 комментария
  • Как адаптировать итеративный алгоритм обхода бинарного дерева к обходу сильноветвящегося дерева?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Разницы нет. Просто теперь потомки каждого узла лучше представлять в виде массива, по которому нужно итерироваться - без left и right

    void Visit(Node node) {
         for (auto child: node.children()) {
               stack.append(child);
         // Не так
         // if (node.left != nullptr) {
         //    stack.append(node.left);
         //  }
         // if (node.right != nullptr) {
         //    stack.append(node.right);
         //  }
       
    }
    Ответ написан
    1 комментарий
  • Как избежать дубликации кода реализуя Trait'ы в Rust?

    bingo347
    @bingo347
    Crazy on performance...
    Написать derive макрос. Правда стоит соизмерить трудозатраты.
    Или написать обычный декларативный макрос (не так гибко как derive, но написать проще).

    А вообще, Rust не Java/C#, trait - не интерфейс.
    Если приведете не абстрактные примеры, вполне возможно, что задача решается проще.
    Ответ написан
    Комментировать
  • Как вызывать код из других языков в Rust?

    Torin_Asakura
    @Torin_Asakura
    Lead Architect
    Обычно для таких целей используются FFI (Foreign Function Interface) или аналогичные либы, которые облегчают жизнь. Если вопрос по коду на Lua, C или Rust, который не известен до момента исполнения, можно сделать что-то в духе:

    Lua из Rust
    Для Lua скриптов можно юзать `rlua` или `mlua`. Эти либы позволяют загружать и выполнять Lua скрипты в рантайме.

    Пример кода с использованием `mlua`:
    use mlua::Lua;
    
    fn main() -> mlua::Result<()> {
        let lua = Lua::new();
        lua.load(r#"
            print("Hello from Lua!")
        "#).exec()?;
        Ok(())
    }


    C из Rust
    Rust имеет на борту поддержку для вызова функций C через FFI. Объявляешь функции C с помощью ключевого слова `extern` и потом вызываешь их напрямую в Rust.

    Пример объявления и вызова функции C:
    extern "C" {
        fn c_function(arg: c_int) -> c_int;
    }
    
    fn main() {
        unsafe {
            c_function(5);
        }
    }


    Динамическая загрузка функций Rust
    Для вызова функций Rust, которые не известны на этапе компиляции, нужно использовать DLLs на Windows или shared objects - .so на Unix-подобных системах. Компилишь функции Rust в такую библиотеку и загружаешь их в
    в рантайм с помощью библиотеки `libloading`.

    Пример кода с использованием `libloading`:
    use libloading::{Library, Symbol};
    
    fn main() {
        let lib = Library::new("path_to_library.so").unwrap();
        unsafe {
            let func: Symbol<unsafe extern fn() -> ()> = lib.get(b"my_function").unwrap();
            func();
        }
    }


    Единственное, важно помнить, что в случае с FFI и загрузкой библиотек в рантайме, тебе придётся использовать `unsafe` код в Rust, так как компилятор не может гарантировать безопасность операций через языковые границы, так что, аккуратней.
    Ответ написан
    Комментировать
  • Какой выбрать стек технологий?

    ThunderCat
    @ThunderCat
    {PHP, MySql, HTML, JS, CSS} developer
    2) Есть видеопоток, на котором, например, обнаруживаются автомобильные номерные знаки и отправляется запрос в базу данных для проверки его наличия. В результате возвращается какой-то результат.
    Обычно делается полная обработка видео до конца, после чего все найденные номера пишутся в базу с метками времени, по необходимости делаются снэпшоты конкретного фрейма и сохраняются отдельно, ссылка на место хранения картинки так же пишется в бд. Далее уже можно делать запросы в бд на сопоставление двух таблиц - имеющегося списка владельцев и распознанных номеров. По необходимости заводится табличка связей, типа найдено юзер.айди / парсед_нумбер.айди для того чтобы не бегать с выборочными запросами по пользователю и т.п...

    3) Для этой базы данных я хочу создать WEB с личной учетной записью и реализацией в виде пользователя - администратора...
    Это базовый функционал любого современного фреймворка, авторизация и роли. Здесь вы никакого функционала по идее не пишете вообще. Только создаете и настраиваете соответствующие роли и права. "создать WEB" в вашем случае логично просто написав АПИ с десятком рутов, далее будет не особо важно будет ли у вас веб страничка или приложение.

    1) PostgreSQL
    Любая рбд. Специфичных задач я тут не вижу, подойдет все что можно установить и с чем вы знакомы лучше.

    2) Python + Tenserflow и/или что-то в этом роде + psycopg2
    Опять же, задача чисто прикладная, любые инструменты выполняющие поставленную задачу подойдут. Производительность и качество можно проверить только тестами на конкретных данных.

    По п.2, ожидается, что не будет необходимости отслеживать сразу несколько объектов и отправлять несколько параллельных запросов. Однако это не исключено.
    Это в любом случае будет работа с командной строкой, любой процесс из которой можно запустить отдельным потоком.

    3) Python + Flask и связанное с этим, например, Bootstrap и тому подобное
    Скорее всего апи на любом фреймворке + какой-нибудь реакт/вью.

    4) Android Studio, Kotlin + что-то для работы с БД
    По описанию скорее какой-нибудь PWA хватит с головой. Вся работа с бд идет через апи, ничего дополнительного особо придумывать не надо.

    Я напоминаю вам, что у меня нет опыта работы с чем-то настолько большим. Спасибо.
    Слона едят по кускам. Разбейте задачи на понятные подзадачи и решайте все в порядке реализации. Каких-то инновационных фичей я тут не вижу, все строится либо на готовых модулях/приложениях, либо на достаточно примитивной логике, так что задача вполне по силам новичку, хоть и придется поработать.
    Ответ написан
    Комментировать
  • Использование HTTP/2 ускорит процесс передачи/принятия ответа от api сервера?

    @Everything_is_bad
    практически не повлияет, оптимизация твоего апи может дать на порядок больше ускорения.
    Ответ написан
    1 комментарий
  • Почему так работают интерфесы в Го?

    Потому что в Го сигнатура метода в интерфейсе должна совпадать полностью. Таким образом на рантайме они быстро матчатся.

    Иначе пришлось бы заглядывать внутрь типа A, а так как это все происходит на рантайме, было бы неоптимально. Возможно для вашей цели больше подойдут дженерики, в их случае происходит мономорфизация и компилятор генерирует отдельный код для каждого варианта дженерика, что работает быстро.

    Кстати, не рекомендую называть интерфейсы ISomething, это не принято в Го.
    Ответ написан
    Комментировать
  • Не могу определиться с пайплайном, как разобраться?

    Mike_Ro
    @Mike_Ro Куратор тега JavaScript
    Python, JS, WordPress, SEO, Bots, Adversting
    Изучил основы JavaScript, понял что всякие манипуляции DOM мне не нужны, потому что это не используется больше

    Где и кем больше не используется?
    Думаю такой, может мне надо выучить React?

    Но есть почему-то ощущение что React в чистом виде мне не нужен, чтобы пользоваться Next.js.

    NextJS: The React Framework for the Web...
    А в "грязном" виде React какой?
    Я остановился и понял что я занимаюсь какой-то фигней. Что я хватаю отовсюду понемногу знаний, но они не складываются в общую картинку.

    Собственно вопрос: по какому пути лучше пойти, чтобы потихоньку прийти к желаемому?

    Все так и есть. Вам необходимо изучать JS в следующем порядке:
    1. Vanilla JS.
    2. React.
    3. Frontend React + NextJS.
    4. Fullstack React + NextJS (+NestJS?).
    При этом чтобы не потратить время впустую на изучения вещей, которые абсолютно не нужны.

    А вот здесь интересный момент. Видите ли, исходя из количества вакансий, NodeJS и все ее производные в качестве backend фреймворков - не сильно востребованы, относительно более специализированных backend языков/фреймворков. Если у Вас нет особой страсти к NodeJS, то рекомендую сфокусироваться лишь на frontend (учитывая, Ваш контекст), а затем (если будет возможность) - учить в дополнение к frontend более специализированные backend языки/фреймворки.
    Ответ написан
    2 комментария
  • Как обновить страницу напрямую через сервер?

    ThunderCat
    @ThunderCat Куратор тега Веб-разработка
    {PHP, MySql, HTML, JS, CSS} developer
    WebSocket
    Ответ написан
    2 комментария
  • Почему в Docker собирается не тот Rust?

    vabka
    @vabka
    Токсичный шарпист
    Как уже выше сказали - cargo не увидел, что src поменялись и не стал собирать заново.
    Определяет он, что файл изменился по дате изменения файла. Если дата изменения файла меньше либо равна дате компиляции, то повторной компиляции не будет.
    Чтобы обновить дату изменения файла - достаточно сделать touch main.rs после первой сборки.
    В docker появился docker init, который сам делает корректный dockerfile - так что в принципе уже и не нужно руками dockerfile писать.
    Генерирует он примерно такое для компиляции (зачем так - описано в комментариях):
    ARG RUST_VERSION=1.71.0
    ARG APP_NAME=project
    FROM rust:${RUST_VERSION}-slim-bullseye AS build
    ARG APP_NAME
    WORKDIR /app
    
    # Build the application.
    # Leverage a cache mount to /usr/local/cargo/registry/
    # for downloaded dependencies and a cache mount to /app/target/ for
    # compiled dependencies which will speed up subsequent builds.
    # Leverage a bind mount to the src directory to avoid having to copy the
    # source code into the container. Once built, copy the executable to an
    # output directory before the cache mounted /app/target is unmounted.
    RUN --mount=type=bind,source=src,target=src \
        --mount=type=bind,source=Cargo.toml,target=Cargo.toml \
        --mount=type=bind,source=Cargo.lock,target=Cargo.lock \
        --mount=type=cache,target=/app/target/ \
        --mount=type=cache,target=/usr/local/cargo/registry/ \
        <<EOF
    set -e
    cargo build --locked --release
    cp ./target/release/$APP_NAME /bin/server
    EOF


    Ещё можно попробовать написать так (этим пользовался я раньше):
    # FROM, Установка rust и прочих зависимостей
    # ...
    
    RUN cargo new /app
    COPY app/Cargo.toml /app/
    
    # This step compiles only our dependencies and saves them in a layer. This is the most impactful time savings
    # Note the use of --mount=type=cache. On subsequent runs, we'll have the crates already downloaded
    WORKDIR /app
    RUN --mount=type=cache,target=/usr/local/cargo/registry cargo build --release
    
    COPY ./app /app
    
    # touch нужен, чтобы изменить дату изменения файла
    RUN --mount=type=cache,target=/usr/local/cargo/registry \
      set -e; \
      touch /app/src/main.rs; \
      cargo build --release;


    Оба варианта позволяют активно использовать фичи кэширования в Docker, чтобы не выкачивать все зависимости и не перекомпилировать их при каждой сборке образа.
    Ответ написан
    Комментировать
  • Почему в моем тесте go быстрее c?

    vabka
    @vabka
    Токсичный шарпист
    1. А почему оптимизации в GCC не включены?

    2. Код не эквивалентный. Зачем ты меряешь скорость printf?

    3. Почему всего 1 прогон? Может 3 секунды - входит в твою погрешность?
    Прогони хотябы по 100 раз и посчитай отклонение
    Ответ написан
  • Как посоветуете выполнять развёртывание web сервера Rust на VDS?

    Negezor
    @Negezor
    Senior Shaurma Developer
    Абсолютно так же как и остальными Node.JS, Go и другими языками в современном мире пакуется в контейнер и деплоится в прод. Есть несколько готовых вариантов, но все они будут придерживаться docker и docker compose:

    - ручное: Клонируем репозиторий, билдим на этом сервере docker compose build && docker compose up -d.
    - ручное: Локально билдим докер образ и пушим в регистр докера, на самой машине так же docker compose pull && docker compose up -d но уже только с получением образа из регистра докера в docker compose.
    - полу-автоматически: Пишем .sh скрипт который на git хуки или руками будет делать действия что и в одном из предыдущих вариантов, но без Workflow.
    - автоматически: Используем GitLab/Github Workflow или любой другой, на каждый релиз/коммит/PR запускаем Workflow с билдом, дальше пушит полученный контейнер в регистр, затем последним этапом будет подключение по SSH к серверу и применения условного
    cd /path/to && docker compose pull && docker compose up -d


    Я привёл самые простые варианты. Ещё есть варианты с k8s, ansible и другими вещами, но это не ваш случай судя по всему.
    Ответ написан
    9 комментариев
  • Как правильно и удобно читать данные из БД?

    vabka
    @vabka Куратор тега C#
    Токсичный шарпист
    1. async-await используй
    2. Используй какую-нибудь orm-ку (EF core, Dapper, linq2db). Многие из них как правило явно запрещают параллельные запросы в рамках одной транзакции.

    Но вроде чисто в теории sqlite разрешает конкурентное чтение (но не запись)
    Ответ написан
    Комментировать
  • Почему скорость чтения из файла резко деградирует?

    dimonchik2013
    @dimonchik2013
    non progredi est regredi
    ну, раз никто не ответил, чуток лекции от меня

    во-первых как сказал ув. Василий Банников -тестировать надо только IO диска
    вот это вот детский сад, так нельзя
    Сначала я прогнал тест на Windows... я и не стал проверять на Windows неделю назад (работал в Docker).
    условия должны быть неизменны

    во-вторых, как говорю я - надо изучить что уже известно по этому вопросу:
    • вот тут товарищи тоже задаются года с 2018
    • а вот и кое-какой продукт

    да, это про IO а не файлы, но - с твоей задачей где-то рядом, если вообще не то что надо , но там много вопросов - ответов, которые расширят твое понимание - например, разное поведение в разных ОС

    в третьих, есть такая штука как кеш диска (а еще есть кеш у харварного рейда, но не всегда), да так что в этой вашей команде DD
    dd if=/tmp/test.img of=/dev/null bs=1M count=1024
    есть спец опция для отклбчения кеша, иначе получается космик цифры

    в четвертых - есть проблема храннеия мелких файлов и вообще файловой системы, тут приведу только два-три слова: самопис ( там почитаешь про суть проблемы), пром1 пром2

    в общем, задачка сильно посложнее чем просто погонять байты
    и, это конечно не мое дело - но "а зачем"? что ты будешь делать с полученной инфой?

    если все же "а зачем" осталось актуальным - я бы делал так:
    1) прогнал прогу для дисков из пример выше
    2) посмотрел бы вдумчиво это видео (увы, не про Rust, но докладчик знает толк в извращениях (с)), в том числе и ввиду твоих проблем с генерацией в памяти

    воообще - сам подход правильный, надо знать максимумы что может язык, если хочешь называться профессионалом, но само решение... поверь - куда проще отталкиваться от уже написанного кем-то рабочего кода
    Ответ написан
    Комментировать