• Насколько правильно использовать package rate против ddos атак?

    @PapaStifflera
    Родился, вырос...
    Рейтлимитеры предназначены не для защиты от (D)DoS-атак, а для ограничения количества запросов на эндпоинт(ы) в единицу времени. А если на ваш сервак пустят хороший поток UDP-трафа, то вас не спасет ни какой рейтлимитер, т.к. до него даже дело не дойдет.
    Ответ написан
    8 комментариев
  • Есть ли разница между горутинами и await в C#?

    Tyranron
    @Tyranron
    Несмотря на то, что эти инструменты созданы для решения одних и тех же проблем, делают они это по-разному, как под капотом, так и в плане предлагаемых абстракций. Потому нельзя сказать что async/await в C# - это "просто обертка над горутинами".

    Горутины в Go - это концепция stackful coroutines (под капотом) + CSP (в абстракциях). Каждый раз, когда мы создаём горутину, под неё выделяется отдельный стек вызовов для её собственных нужд. При этом, когда происходит паника, то stack unwinding (размотка стека вызовов) происходит только в пределах этой горутины и не покидает границ её стека. Стек горутины полностью отвязан от стека её создания/вызова, потому горутина не может возвращать результат. Любое общение между горутинами выполняется либо посредством каналов, либо какой-то общей памяти.

    async/await в C# (то есть, Task'и) - это концепция stackless coroutines (под капотом) + futures (в абстракциях). Код с async/await'ами компилятор превращает в определенную стэйт-машину с yield point'ами. У них нет отдельного стека, они выполняются в том же стеке что и вызывающий их код. Соотвественно, есть возможность словить exception'ы (аналог panic'и) возникающие внутри асинхронного Task'а прямо в запускающем его коде. Так как выполнение идёт на том же стеке - Task нормально может возвращать результат и мы его можем считать в вызывающем коде без дополнительных примитивов/инструментов.

    При этом, если мы запустим Go с GOMAXPROCS=1, то мы получим однопоточный асинхронный код в Go (по умолчанию он многопоточный). Также и в C# мы можем выполнять Task'и как на одном потоке, так и на thread pool, получая аналогичные Go гарантии рантайма.

    С точки зрения абстракций/использования - это уже вкусовщина. Кому как больше нравится. У futures лучше дизайн в плане composability (их эргономичнее join'ить и select'ить), но они вынуждают писать везде async и await. У горутин надо постоянно городить чехарду с синхронизацией (попробуйте сделать аналог await для произвольной горутины), но если эту чехарду прятать под капот (как обычно и делают), то код вообще выглядит полностью синхронным и программисты радуются.
    Ответ написан
    4 комментария
  • Стоит ли избегать знака присваивния := в Go при нагруженном бекенде?

    Tyranron
    @Tyranron
    Это неважно.
    Не следует "экономить на спичках" и соблюдать пустые ритуалы. Вы пишите приложение нормально, чтобы его понимали и нормально читали другие разработчики. Когда же дело доходит до оптимизации, Вы профилируете и смотрите где конкретно у Вас проблемы и затыки. Их и убираете.

    Что же касается конкретно аллокаций, то всё не совсем так (вернее, совсем не так).
    Аллокация - это выделение куска памяти в куче (heap), который потом должен быть убран сборщиком мусора. Именно потому это и считается ударом по производительности, так как добавляет работы как аллокатору, так и сборщику мусора.
    Но использование := само по себе не включает/выключает использование аллокации. Оно лишь декларирует новую переменную.
    Будет ли произведена аллокация зависит от другого. В первую очередь, от того какие Вы данные создаёте. Если это примитивный тип фиксированного размера, размещаемый на стэке (например int), то работы с кучей у Вас не будет вовсе, соответственно и аллокаций. Во вторую очередь, от такой магической штуки как escape analysis, которая может запросто разместить данные из кучи на стэке, если ей так того захочется, тогда аллокации у Вас происходить тоже не будет.

    Давайте посмотрим примеры:
    1. var i int
      i = 1
      i = 2

      0 аллокаций, так как i размещается строго на стэке.

    2. i := 1
      i := 2

      0 аллокаций, так как i размещается строго на стэке.

    3. i := new(Struct{1,2,3})
      i := new(Struct{3,2,1})

      2 аллокации, так как new разместит данные в куче и вернёт указатель на них. Но только если escape analysis не переместит это всё в стэк (что конкретно в данном случае достаточно вероятно).

    4. var i *Struct
      i = new(Struct{1,2,3})
      i = new(Struct{3,2,1})

      2 аллокации, так как new все ещё разместит данные в куче и вернёт указатель на них.



    Как Вы видите, := сам по себе никак к аллокациям не относится, и является лишь синтаксическим сахаром.

    P.S. Давеча на Хабре была отличнейшая статья про стандартную библиотеку Go, показывающая что занятие преждевременными микрооптимизациями без профилирования - вполне себе бессмысленная затея.
    Ответ написан
    Комментировать
  • Пример архитектуры хорошего Golang веб-приложения?

    @alexkdev
    Сам нахожусь в поисках идеального ответа на ваш вопрос, но кое что есть для размышления по этому поводу:
    1. https://github.com/gothinkster/realworld (тут не только Golang)
    2. https://github.com/golang-standards/project-layout
    Ответ написан
    Комментировать
  • Как бы вы начали обучение go?

    @RidgeA
    Ответ написан
    Комментировать
  • Как вывести список всех файлов с расширением txt и csv?

    BuriK666
    @BuriK666
    Компьютерный псих
    err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
    		if !info.IsDir() {
    			ext := filepath.Ext(path)
    			if ext == ".txt" || ext == ".csv" {
    				files = append(files, path)
    			}
    		}
    		return nil
    	})
    Ответ написан
    Комментировать
  • Какая разница в цикле for между "i ++" и "++ i"?

    dom1n1k
    @dom1n1k
    В данном случае присваивания не делается, поэтому никакой разницы в смысле результата работы нет.
    Есть разница в смысле скорости (++i работает немного быстрее), но она настолько микроскопическая, что на неё нужно смело забивать в 99.(9)% случаев. Возможно даже, что сейчас компиляторы ловят эту ситуацию и тогда разница исчезает вовсе.
    Сам я пишу ++i, но не ради перфоманса, это просто моя исторически сложившаяся вкусовщина.
    Нужно просто выбрать один кодстайл (личный или корпоративный) и придерживаться его. Смешивать два варианта в пределах одной программы - это плохо.
    Ответ написан
    Комментировать
  • Как настроить IntelliSense для Go для Visual Studio Code?

    @alexstup
    Оркестр
    Вам надо положить ваши пакеты в GOPATH/src/... директорию, т.е. там куда скачиваются пакеты при добавлении.
    Тогда будет видеть.
    Ответ написан
    5 комментариев
  • Как на 100% отключить доступ в интернет?

    @Wexter
    Сетевой разъём и порты usb залить термоклеем, устройство в клетку фарадея чтобы никакой радиосигнал не проникал.
    Ответ написан
    4 комментария
  • Как на 100% отключить доступ в интернет?

    GavriKos
    @GavriKos
    Выпаять разъем и вайфай-адаптер. Хотя в таком случае тот кто сядет за устройство может впаять их обратно.
    Ответ написан
    Комментировать
  • Для изучения стереометрии: есть ли программа для построения объемных фигур?

    GeoGebra (как «Геометрия» + «Алгебра»)
    Ответ написан
    Комментировать