image


Продолжаем публикацию наших образовательных материалов. Этот курс посвящен изучению основ языка Go. На примере простой текстовой игры будут рассмотрены все основные задачи, с которыми сталкивается разработчик современных веб-приложений в крупных проектах, с реализацией их на Go. Курс не ставит задачи научить программированию с нуля, для обучения будут необходимы базовые навыки программирования.


Список лекций:



Вы получите опыт разработки высоконагруженных бекенд приложений на Go, а также научитесь поддерживать, тестировать и отлаживать приложения. Из курса вы узнаете о том, как поднять веб-сервер, обрабатывать HTTP-запросы и работать с SQL-базой; что такое горутины c каналами и как выглядит асинхронное программирование на Go; какие основные вещи требует экcплуатация при принятии проекта в production.


Курс ведут Василий Романов, технический менеджер Почты Mail.Ru, Илья Ожерельев, программист backend'a Почты Mail.Ru, и Дмитрий Дорофеев, программист frontend'a Почты Mail.Ru.


Лекция 1. Введение



Вводная лекция, в которой описывается история языка, его основные особенности, использование Go в Mail.ru, основные синтаксические конструкции языка и базовые типы данных.


Лекция 2. Функции, структуры, интерфейсы. Объектная модель



На второй лекции рассматриваются следующие вопросы:


Функции:


  • Передача параметров по ссылке/значению.
  • Именованные параметры.
  • Замыкания.
  • Функции высшего порядка.
  • defer.
  • Системные функции.

Структуры:


  • struct, ООП.
  • Методы.
  • Embedded-объекты.

Интерфейс:


  • Пустой интерфейс.
  • Использование интерфейсов.

Лекция 3. Асинхронная модель



На третьей лекции рассматриваются параллелизм и многопоточность языка, Go-рутины (горутины), каналы, пакеты sync и atomic.


Лекция 4. Web. Работа с сетью



Из этой лекции вы узнаете о работе Go с сетью: работа с протоколом TCP, какие есть ограничения, особенности работы с URL, как строятся HTTP-запросы и ответы, и многое другое.


Лекция 5. Работа с СУБД



На пятой лекции рассказывается о клиентской (браузерной) части при работе с СУБД, а также о серверной части: построении бизнес-логики, создании сессии авторизации, профиля и работе с контентом.


Лекция 6. Система тестирования



Лекция посвящена построению системы тестирования для проверки кода на Go, вклбючая модульные тесты и выполнение непрерывной интеграции.


Лекция 7. Reflect or generate?



На лекции рассматриваются такие вопросы, как что такое рефлексия, законы рефлексии, использование go generate и так далее.


Лекция 8. Производительность



Как выявить медленно работающие части кода на Go и как их оптимизировать так, чтобы программа работала быстро в условиях ограниченности доступных ресурсов? Об этом вы узнаете из восьмой лекции.


Лекция 9. Context, unsafe, cgo



Заключительная лекция курса посвящена рассмотрению трёх тем: контекста (состояние запроса, отмена выполнения), unsafe (низкоуровневое программирование) и cgo (интеграция кодов на Go и С).




Плейлист всех лекций находится по ссылке. Напомним, что актуальные лекции и мастер-классы о программировании от наших IT-специалистов в проектах Технопарк, Техносфера и Технотрек по-прежнему публикуются на канале Технострим.

Поделиться с друзьями
-->

Комментарии (51)


  1. ainu
    10.05.2017 15:59

    Спасибо! Насколько я вижу, уровень выше (и ценнее!) среднего youtube-ролика а-ля «основы Golang» или «как мы уменьшали stop-the-world в GC»


    1. ainu
      10.05.2017 16:03

      А ещё советую в заголовок, текст или в теги добавить «golang». Это общепринятая рекомендация для именования материалов, чтобы было проще гуглить.


      1. igordata
        11.05.2017 08:14

        Я тоже за golang, потому go гуглится с трудом, т.к. является распространённым словом.


  1. beduin01
    10.05.2017 17:27
    +3

    Судя по тому что рассказывают докладчики у Go есть только одно преимущество, можно легко и быстро создавать кучу легковесных потоков. В остальном не язык, а один сплошной архаизм поощряющий костылестроение в попытках обойти его конструктивные недостатки.


    1. ainu
      10.05.2017 17:39

      Код, не использующий потоки, на Go тоже легко и быстро пишется. Парсеры/серверы/утилиты.


      1. VolCh
        11.05.2017 10:31

        В наше время есть серверы, не использующие ту или иную реализацию параллельного выполнения запросов от клиентов?


        1. ainu
          11.05.2017 10:43

          В наше время есть программы, которые работают не на сервере.
          В наше время есть cli-утилиты (например, сконвертить один файл в другой)
          В наше время есть однопоточный bolt.

          Параллельность — это ещё не всё.
          Go — это не «язык с прикольной параллельностью, но вот жаль нет дженериков, ООП, эксепшенов, тьфу убогая архитектура».

          На Go действительно можно быстро писать код, и не только многопоточный/конкуррентный.
          Прошу заметить, что это не означает, что нельзя программировать на D/Rust/Scala/etc.


          1. ainu
            11.05.2017 10:48

            Справедливости ради озвучу (хотя тут все это понимают), что любой сервер под капотом использует многопоточность в том или ином ей виде. Go-шный net/http сервер — тоже. Однако можно написать http сервер на Go (на основе net/http) и в коде не будет ни одного вызова go funcName().


          1. VolCh
            11.05.2017 10:52

            Я уточнял исключительно про серверы.


    1. beduin01
      10.05.2017 17:40
      +1

      Я еще раз сделаю акцент на том, что Go подходит для создание кучи легковесных потоков, но совершенно не подходит для обработки данных (хотя если упороться можно хоть числодробилку на PHP написать).


      package main
      
      import "fmt"
      
      func int64Sum(list []int64) (uint64) {
          var result int64 = 0
          for x := 0; x < len(list); x++ {
              result += list[x]
          }
          return uint64(result)
      }
      
      func int32Sum(list []int32) (uint64) {
          var result int32 = 0
          for x := 0; x < len(list); x++ {
              result += list[x]
          }
          return uint64(result)
      }
      
      func int16Sum(list []int16) (uint64) {
          var result int16 = 0
          for x := 0; x < len(list); x++ {
              result += list[x]
          }
          return uint64(result)
      }
      
      func int8Sum(list []int8) (uint64) {
          var result int8 = 0
          for x := 0; x < len(list); x++ {
              result += list[x]
          }
          return uint64(result)
      }
      
      func main() {
      
          list8  := []int8 {1, 2, 3, 4, 5}
          list16 := []int16{1, 2, 3, 4, 5}
          list32 := []int32{1, 2, 3, 4, 5}
          list64 := []int64{1, 2, 3, 4, 5}
      
          fmt.Println(int8Sum(list8))
          fmt.Println(int16Sum(list16))
          fmt.Println(int32Sum(list32))
          fmt.Println(int64Sum(list64))
      }

      Тоже самое на D. В которому впрочем поддержка этих же легковесных потоков тоже есть.


      import std.stdio;
      import std.algorithm;
      
      void main(string[] args)
      {
          [1, 2, 3, 4, 5].reduce!((a, b) => a + b).writeln;
      }
      


      1. RPG18
        10.05.2017 18:07
        +1

        но совершенно не подходит для обработки данных

        У каждого свои данные. Я вот пишу что-то типа Socorro, но с поддержкой emscripten. Данными являются файлы символов, минидампы, то что сваливается в GlobalEventHandlers.onerror.


      1. ReklatsMasters
        10.05.2017 22:14

        А можно простейший пример этих легковесных потоков на D? Просто интересно сравнить.


        1. beduin01
          11.05.2017 09:52

          1. kilgur
            11.05.2017 12:47

            Это все-таки разные вещи. Как минимум, в файберах управление переключается явно.


          1. Weres
            16.05.2017 11:18
            +1

            Yield нужно расставлять руками (в golang умный шедуллер) и распределением фиберов по тредам придётся, опять же, заниматься руками. Штука всё равно хорошая и D куда более мощный и приятный язык, чем Go, но всё-таки горутины куда более продвинуты.


      1. KEKSOV
        11.05.2017 13:46
        +1

        Простите, но Ваш пример, демонстрирующий «невозможность организовать на golang обработку данных», не выдерживает никакой критики. Лаконичность кода на D — да. C тем же успехом можно написать строчку на JS

        [0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, index, array) {
          return previousValue + currentValue;
        });
        
        и сказать, что JS аж на пять строк короче, чем D…

        А как насчёт сопровождения такого кода? Как насчёт отлова ошибок с данными на этапе компиляции? Тесты производительности гоняли?


        1. xucixe
          16.05.2017 11:17
          +4

          Так писали лет 10 назад. Сейчас на JS эта задача решается гораздо проще:

          [0,1,2,3,4].reduce((item, sum) => item + sum);
          


          А вот вам пример на php:
          array_sum(range(0, 4));
          


          Вывод: php круче всех :)


          1. kainsk
            16.05.2017 23:10
            +1

            вот APL:

            +/?5


      1. madkite
        11.05.2017 16:13
        +2

        В Вашем примере на D только один массив непонятного размера и бизнес-логика (суммирование) не вынесено в отдельную функцию. Если же создать 4 массива с элементами разных размеров и не инлайнить функцию суммирования (а написать template, который будет понимать разные типы), то кода будет чуть больше… Но в целом Ваши негодования понятны — отсутствие в стандартной библиотеки функции reduce (есть сторонние реализации) и отсутствие generic-ов — на эту тему уже много написано, даже авторами языка.


        1. beduin01
          12.05.2017 13:08
          -1

          Так же авторы языка делали Go для мелких утилит в 100-150 строк кода, поэтому Go в больших проектах это в первую очередь геморрой т.к. он не позволяет делать элементарные абстракции и обобщения.


          Даже Python на фоне Go смотрится куда более продуманным и совершенным языком.


      1. roma_dev
        16.05.2017 11:17

        можете привести пример где go «совершенно не подходит для обработки данных»?


      1. nizsheanez
        16.05.2017 11:18
        -1

        Да, в примерах Go выглядит именно так, но в реальных проектах редко спотыкаешься о то что под каждый тип надо свой метод писать. У нас много разных сервисов на Go, и таких функций как в примере, ну может 2-3 от силы, а 2-3 функции в common это примерно 0% от кода проекта.


        1. JekaMas
          17.05.2017 10:28
          -1

          Соглашусь. Только на низком уровне с этим есть сложности и при потребности в максимальной прроизводительности: иначе же можно спокойно жить с fmt sync.map и прочим, принимающим и отдающим interface{} и не столкнуться с проблемами, ни кода ни производительности.
          Мне кажется, что желание дженериков везде и всегда, сродни преждевременной оптимизации или неоправданному расширению задачи: надо было сделать для одного типа, но программист пробует написать обобщенный код.
          Дженерики нужны, конечно, кодогенерация не помогает всегда, да и код усложняет в разы, как и отладку сгенерированного кода. И в самой стандартной библиотеке она не используется, то есть это решение и разработчикам golang не сильно нравится.
          Но да, дженерики не настолько важны в действительной жизни. Рабочий код пишется и без них.


      1. kainsk
        16.05.2017 11:18

        То же на APL:

        +/1 2 3 4 5


      1. kshvakov
        16.05.2017 11:18
        -1

        Это слишком «притянутый за уши» пример, как по мне, например, лучше один раз создать пакет sum (Int8, Int16 etc) и использовать его в проекте

        package main
        
        import "sum"
        
        func main() {
           println(sum.Int8([]int8 {1, 2, 3, 4, 5}))
        }
        


        чем пытаться понять из какого пакета прилетела функциональность writeln или reduce (соответственно, чем больше проект и больше пактов, тем сложнее, опять же для меня, все это поддерживать), так что только на основании этого я бы не стал утверждать, что он (Go) категорично не подходит для обработки данных

        ЗЫ: и у D и у Go есть свои плюсы, но Go, в моем случае, предпочтительнее в силу своей очевидности


  1. mnv
    10.05.2017 18:24

    Не работал с Go, но слышал, что там не реализованы исключения. Есть ли какой-то устоявшийся альтернативный подход к выбрасыванию и обработке исключений?


    1. kilgur
      10.05.2017 20:57
      +2

      Вы потролить зашли? :) Запрос в гугле «golang обработка исключений» выдает ответ на ваш вопрос на stackoverflow и несколько статей (в том числе и на хабре) про обработку ошибок в go.


      1. mnv
        10.05.2017 23:31
        -4

        Почему же. Дело в том, что вместо привычного механизма исключений в Go предлагается несколько вариантов, но все они с первого взгляда какие-то неудобные. Есть даже библиотеки, которые пытаются воспроизвести что-то близкое к привычным исключениям. Может это и нормально, но для человека, не работающего с Go, это выглядит странно. Поэтому вполне нормальный вопрос.


        1. kilgur
          11.05.2017 07:43

          Я понимаю, почему вы ищете исключения в go — «привычный механизм», я не понимаю зачем? Например, вы привыкли ездить на велосипеде, видите как другие ездят на самокатах и удивляетесь — зачем они ногами от земли отталкиваются, есть же классная штука — педали, которые можно крутить… и ищете педали на самокате… даже где-то видели возможность прикрутить педали к самокату. Зачем? Если для вас важен механизм исключений при разработке, а обработка ошибок как возвращаемых значений в go кажется вам неудобной, не изучайте go. Есть множество других языков с исключениями.
          Мне вот не понравился rust, не смог привыкнуть к его «свистульками и погремушкам», причем на уровне ощущений и эмоций, т.е. я не смогу объяснить — чем именно не понравился. Нет, так нет, я и не читаю статьи про rust.


          1. kilgur
            11.05.2017 12:05

            Минусуют фанаты rust'а? Это я неудачный пример привел… холиварный. Буду иметь в виду.


            1. DarkEld3r
              12.05.2017 12:36
              +1

              А что раст? Там тоже "нет исключений". Просто перестроится сложно и не всегда понятное даёт ли это хоть какие-то преимущества. Люди привыкли жить с исключениями и находят в этом определённое удобство. Тут надо показать преимущества другого подхода, а не просто предлагать забыть о предыдущем опыте.


              1. kilgur
                12.05.2017 13:17

                Я не предлагаю забыть предыдущий опыт. Я немного о другом. В каждом языке есть свои особенности и, касаемо go, у разработчика нет выбора в подходе обработки ошибок — нельзя выбрать «go с исключениями» или «go с возвращаемыми ошибками». Выбор есть только выше уровнем — go или «не go». Если кому-то важны именно исключения, значит go следует вычеркнуть из списка «следующий язык программирования для изучения». Если жизнь не мила без дженериков — аналогично. Я об этом.
                А «не фигово было бы изучить go, но в нем обработка ошибок какая-то неудобная...» я не понимаю. После подобного хочется спросить «Ииии?!» Дальше-то что? Если человек хочет узнать, как эта неудобная обработка ошибок работает и как ей пользоваться, ну, так «google в помощь» — информации навалом.
                А про раст — мне неважно, есть там исключения или нет; если у меня хватит терпения и времени я приму его модель и неважно — насколько она отличается от go, python, php, lua (других языков я не знаю).


                1. mkevac
                  12.05.2017 13:47
                  -1

                  Все так. Вы правильно в начале написали.


          1. q1t
            16.05.2017 11:18
            +2

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


            1. kilgur
              17.05.2017 09:00
              -2

              Полностью с вами согласен. Но я себе выбирал не инструмент для каких-то конкретных задач, а тему для саморазвития, чтобы мозги «не кисли». Поэтому не стал «копать» — что именно меня не устроило в rust'е. По мелким админским задачам python'а хватает «за глаза», т.ч. я и Go пока не нашел применения на работе, к сожалению.


        1. VolCh
          11.05.2017 10:41
          +4

          Для человека, работавшего со, скажем так, Фортран и Си-подобными языками, некоторые варианты, предлагаемые Go, в частности возвращение из функций двух значений, одно из которых является и признаком, и сообщением об ошибке, являются куда более удобными, чем привычное либо возвращение ошибки магическим числом, либо падение процесса. Привычные по С++ подобным языкам исключения с раскруткой стека вызовов чащего всего используются не по назначению, не для обработки исключительных ситуаций, а для ветвления в зависимости от каких-то определенных условий.


  1. kilgur
    10.05.2017 18:56
    +6

    Простите, но уровень лекций — «ниже плинтуса». Может, это слишком субъективно, но я не смог досмотреть ни одной лекции. Хватило терпения только на 3. Я понимаю — парни волнуются, они разработчики, а не преподаватели. Но тем более тогда лучше сделать публичную версию специально отснятой — с монтажем, дублями и т.п. Видео и так очень отстает от книг в плане скорости подачи информации, а в этих лекциях скорость становится просто черепашьей, к сожалению. ИМХО, книга Кернигана и Донована за аналогичное время даст больше информации и основы go будут понятнее.


    1. VolCh
      11.05.2017 10:43

      Уровень лекций как способа подачи материала или самого материала?


      1. kilgur
        11.05.2017 12:02
        +2

        Как способа подачи материала, в первую очередь. Трудно оценить качество материала при низком качестве его подачи.


  1. kilgur
    11.05.2017 12:01

    del (промахнулся)


  1. JekaMas
    11.05.2017 14:59
    +1

    Во первых, мое почтение за большую работу. Сейчас это самый полный материал по Golang, по крайней мере, на русском языке.
    Но для пробы посмотрел вторую лекцию и был удивлен: в лекции рассматриваются вопросы, которых или не существует или они по-другому работают в go. Рассмотрена передача параметров по ссылке и значению, но в go есть только передача по значению; предупреждается о переполнении стэка — ну это возможно, если всю память переполнить, впринципе…


    1. claygod
      17.05.2017 09:50

      Рассмотрена передача параметров по ссылке и значению, но в go есть только передача по значению
      В Golang есть передача по указателю ( http://golang-book.ru/chapter-08-pointers.html ) ну и для особых случаев пакет unsafe если уж действительно надо поработать на низком уровне.


      1. JekaMas
        17.05.2017 10:21
        +1

        Указатель не есть тоже самое, что ссылка.
        Можно сделать указатель, но в функцию его передашь все равно по значению. С unsafe то же самое. Ну будет uintptr — это не ссылка, а вполне себе значение.


        1. claygod
          17.05.2017 11:39
          +1

          Давно я не брал в руки шашки.., но по сути, ссылка, это неизменяемый указатель… Можете написать пример кода на Go, в котором именно ссылка а не указатель потребовались, и так, чтобы именно существенно? (В вопросе нет иронии, плз, поделитесь проблемой).


          1. JekaMas
            17.05.2017 13:48

            Ну проблемы нет, есть неверный материал в лекциях, в частности из-за непонимания того, что в go есть только передача по значению можно написать такой неверный код


            1. JekaMas
              17.05.2017 13:53

              Чуть нагляднее даже так
              Если считать, что в go есть передача по ссылке и типы slice, map и chan ссылочные, то такую ошибку сделать легко.


  1. l0rda
    16.05.2017 10:34

    Идея хорошая, но как уже писали — качество хромает, некоторых лекторов просто невозможно слушать. Если их научить не делать ээээ, убрать слова-паразиты и тп, все получится. Но хоть какой-то контент на русском стал появляться по гоу, за это спасибо.


  1. AndrewDr
    16.05.2017 11:18

    Спасибо за видео.


  1. tdav
    16.05.2017 11:18

    Спосибо


  1. pfihr
    18.05.2017 23:40

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


    1. Olga_ol
      19.05.2017 13:27

      Спасибо. Передала преподавателям.