One place for hosting & domains

      Как

      Sysadmin eBook: Как заставить серверы работать


      Загрузите полную электронную книгу!

      Электронная книга «Как заставить серверы работать: практическое руководство по системному администрированию» в формате EPUB

      Электронная книга «Как заставить серверы работать: практическое руководство по системному администрированию» в формате PDF

      Описание электронной книги

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

      Книга основана на учебном курсе «Как заставить серверы работать: практическое руководство по администрированию систем Linux», который можно найти в сообществе DigitalOcean. Она включает несколько основных тем:

      1. Вводные темы

      2. Технологические стеки LAMP и LEMP

      3. Обеспечение безопасности серверов

      4. Автоматизация с помощью Ansible

      5. Контроль версий и непрерывная интеграция

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

      Загрузить электронную книгу

      Вы можете загрузить электронную книгу в формате EPUB или PDF по одной из следующих ссылок.

      Загрузите полную электронную книгу!

      Электронная книга «Как заставить серверы работать: практическое руководство по системному администрированию» в формате EPUB

      Электронная книга «Как заставить серверы работать: практическое руководство по системному администрированию» в формате PDF

      Дополнительные ресурсы для системных администраторов, которые помогут вам начать работать в этой области и участвовать в сообществе DigitalOcean вместе с другими разработчиками и администраторами, можно найти в нашей постоянно растущей библиотеке обучающих руководств, ответов на вопросы и проектов с тегом Getting Started (Начало работы).



      Source link

      Как записывать сеансы терминала и обмениваться ими при помощи Terminalizer в Ubuntu 18.04


      Автор выбрал фонд Electronic Frontier Foundation для получения пожертвований в рамках программы Write for DOnations.

      Введение

      Terminalizer — приложение записи терминала, позволяющее записывать сеанс терминала в реальном времени и воспроизводить его позже. Он работает таким же образом, как и устройство записи рабочего стола, но в терминале.

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

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

      Предварительные требования

      Для данного обучающего руководства вам потребуется следующее:

      Если вы хотите поделиться своими записями в онлайн-режиме, вам понадобится следующее:

      Подготовив все вышеперечисленное, войдите на сервер без привилегий root, чтобы начать подготовку.

      Шаг 1 — Установка Terminalizer

      На этом шаге вы скачаете и установите Terminalizer в вашей системе. Terminalizer написан с помощью Node.js и может быть установлен с помощью диспетчера пакетов npm.

      Чтобы установить Terminalizer на глобальном уровне в вашей системе, выполните следующую команду:

      • sudo npm install --global --allow-root --unsafe-perm=true terminalizer

      Terminalizer использует каркас приложений Electron для экспорта зарегистрированных сеансов терминала в формат GIF. Для установки Electron на глобальном уровне в вашей системе требуется аргумент команды --unsafe-perms=true.

      После установки Terminalizer вы увидите примерно следующий вывод:

      Output

      . . . /usr/local/lib └── terminalizer@0.7.1

      Далее проверьте установку Terminalizer, запустив следующую команду:

      Будет выведен текст следующего вида:

      Output

      0.7.1

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

      Результат будет выглядеть примерно следующим образом:

      Output

      The global config directory is created at /home/user/.terminalizer

      Теперь, когда вы установили Terminalizer, можно сделать первую запись терминала.

      Шаг 2 — Запись и воспроизведение сеанса терминала

      На этом шаге вы записываете и воспроизводите сеанс терминала.

      В начале настройте новую запись Terminalizer с помощью имени на ваш выбор:

      • terminalizer record your-recording

      В результате будет выведено следующее, чтобы указать, что запись началась:

      Output

      The recording session has started Press Ctrl+D to exit and save the recording

      Теперь вы можете перейти к любым необходимым действиям в вашем терминале. Каждое нажатие клавиши и команда будут записываться в реальном времени в Terminalizer.

      Например:

      • pwd
      • date
      • whoami
      • echo "Hello, world!"

      Когда хотите остановить запись, нажмите CTRL+D. Затем Terminalizer сохранит запись в указанном файле в формате YAML, например your-recording.yml.

      Output

      Successfully Recorded The recording data is saved into the file: /home/user/your-recording.yml

      Возможно, Terminalizer предложит поделиться записью в онлайн-режиме. Сейчас нажмите CTRL+C для отмены этого, поскольку вы можете сначала воспроизвести запись терминала локально.

      Далее воспроизведите ваш записанный сеанс терминала при помощи следующей команды:

      • terminalizer play your-recording

      В результате записанный сеанс будет воспроизведен в реальном времени в вашем терминале:

      Output

      user@droplet:~$ pwd /home/user user@droplet:~$ date Sun Mar 8 14:55:36 UTC 2020 user@droplet:~$ whoami user user@droplet:~$ echo "Hello, world!" Hello, world! user@droplet:~$ logout

      Также вы можете изменять скорость воспроизведения вашей записи при помощи опции --speed-factor.

      Например, следующее действие будет воспроизводить вашу запись в два раза медленнее (½ скорости):

      • terminalizer play your-recording --speed-factor 2

      Также вы можете воспроизвести запись в два раза быстрее (скорость х 2):

      • terminalizer play your-recording --speed-factor 0.5

      Вы записали и воспроизвели сеанс терминала. Далее вы можете поделиться записью терминала в онлайн-режиме.

      Шаг 3 — Обмен записанными сеансами терминала

      На этом шаге вы поделитесь своим записанным сеансом терминала в онлайн-режиме на странице изучения Terminalizer.

      Сначала выберите записанный сеанс, которым вы хотите поделиться:

      • terminalizer share your-recording

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

      Output

      Please enter some details about your recording ? Title Title of Your Recording ? Description Description of Your Recording ? Tags such as git,bash,game Comma-separated Tags for Your Recording

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

      Если вы впервые поделились записанным сеансом с помощью Terminalizer, вам нужно будет привязать свою учетную запись Terminalizer. Terminalizer отобразит ссылку для подтверждения, если это потребуется:

      Output

      Open the following link in your browser and login into your account https://terminalizer.com/token?token=your-token When you do it, press any key to continue

      Предупреждение. Убедитесь, что ваш токен Terminalizer остается приватным, т. к. он позволяет любому пользователю, владеющему им, получить доступ к вашей учетной записи Terminalizer.

      После того как вы прошли по ссылке в вашем браузере и вошли в вашу учетную запись Terminalizer, нажмите любую клавишу, чтобы продолжить.

      Теперь Terminalizer загрузит вашу запись и предоставит ссылку для ее просмотра:

      Output

      Successfully Uploaded The recording is available on the link: https://terminalizer.com/view/your-recording-id

      Пройдя по ссылке в браузере на настольном компьютере, вы сможете просматривать записи, которыми вы поделились:

      Скриншот веб-сайта Terminalizer, показывающий пример записи терминала, которой вы поделились

      Вы поделились записанным сеансом терминала на веб-сайте Terminalizer и просмотрели его в браузере.

      Шаг 4 — Настройка расширенной конфигурации Terminalizer

      Теперь, когда вы ознакомились с Terminalizer, вы можете начинать рассматривать некоторые более расширенные опции персонализации, такие как способность изменять цвета и стили отображения.

      Каждая запись наследует конфигурацию по умолчанию из глобального файла конфигурации Terminalizer, который находится в ~/.terminalizer/config.yml​​​. Это означает, что вы можете изменять конфигурацию для отдельных записей напрямую, изменяя файл записи (например, your-recording.yml). Также вы можете изменять глобальную конфигурацию, которая будет влиять на все новые записи.

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

      Сначала откройте файл глобальной конфигурации Terminalizer в текстовом редакторе, например nano:

      • nano ~/.terminalizer/config.yml

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

      Есть несколько стандартных вариантов конфигурации, которые вы, возможно, захотите изменить по вашему желанию:

      • cols: в явном виде задает количество столбцов терминала, используемых для записи.
      • rows: в явном виде задает количество строк терминала, используемых для записи.
      • frameDelay: переопределяет задержку между каждым нажатием клавиши во время воспроизведения.
      • maxIdleTime: указывает максимальное время между нажатиями клавиш во время воспроизведения.
      • cursorStyle: указывает стиль курсора умолчанию на выбор из прямоугольника, полосы и подчеркивания.
      • fontFamily: указывает список предпочитаемых шрифтов воспроизведения в порядке предпочтения.
      • theme: изменяет цветовую схему воспроизведения, например для создания черно-белого терминала и т. п.

      Например, вы можете сделать бело-черный дисплей терминала, настроив следующие опции:

      config.yml

      . . .
      theme:
        background: "white"
        foreground: "black"
      . . .
      

      Результат будет выглядеть примерно так:

      Скриншот веб-сайта Terminalizer, показывающий пример записи с черно-белой темой

      Вы можете изменять стиль курсора, упрощая понимание записи, например, посредством изменения курсора по умолчанию в виде прямоугольника на курсор в виде подчеркивания:

      config.yml

      . . .
      cursorStyle: underline
      . . .
      

      Результат будет выглядеть примерно так:

      Скриншот веб-сайта Terminalizer, показывающий пример записи с курсором в виде подчеркивания​​

      После внесения всех необходимых изменений сохраните файл и возвращайтесь в терминал.

      Если вы изменили глобальную конфигурацию Terminalizer, эти настройки будут применяться ко всем новым записям, выполняемым далее. Если вы изменяете конфигурацию конкретной записи, Terminalizer немедленно применяет изменения к этой конкретной записи.

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

      На этом последнем шаге вы рассмотрели некоторые из расширенных вариантов настройки конфигурации в Terminalizer.

      Заключение

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

      Если вы хотите сделать рендеринг и экспорт записей Terminalizer в формат GIF, вы можете установить Terminalizer на компьютере с графическим интерфейсом пользователя/на настольном компьютере и использовать встроенные функции рендеринга:

      Также вы можете посетить веб-сайт Terminalizer, чтобы увидеть записанные сеансы терминала, которыми поделились другие пользователи:



      Source link

      Как создавать циклы For в Go


      Введение

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

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

      В этом обучающем руководстве вы узнаете, как работают циклы for в Go, включая три основных способа его использования. Начнем с демонстрации того, как можно создавать разные типы цикла for, а затем узнаем, как создавать циклы с помощью последовательных типов данных в Go. А закончим на объяснении того, как использовать вложенные циклы.

      Объявление цикла ForClause и циклов с условием

      Чтобы учесть самые разные случаи использования, существует три разных способа создания циклов for в Go, каждый из которых имеет свои возможности. Вы можете создать цикл for с условием, ForClause и RangeClause. В этом разделе мы расскажем, как объявлять и использовать ForClause и цикл с условием.

      Давайте посмотрим, как мы можем использовать цикл for с ForClause.

      Цикл ForClause определяется как цикл с инициирующим оператором, за которым следует условие и пост-оператор. Они имеют следующий синтаксис:

      for [ Initial Statement ] ; [ Condition ] ; [ Post Statement ] {
          [Action]
      }
      

      Чтобы объяснить, что делают компоненты выше, давайте рассмотрим цикл for, который выполняет увеличение в указанном диапазоне значений с помощью синтаксиса ForClause:

      for i := 0; i < 5; i++ {
          fmt.Println(i)
      }
      

      Давайте разобьем этот цикл на части и рассмотрим каждую часть.

      Первая часть цикла — i := 0. Это инициирующий оператор:

      for i := 0; i < 5; i++ {
          fmt.Println(i)
      }
      

      Он указывает, что мы объявляем переменную с именем i и задаем первоначальное значение 0.

      Далее идет условие:

      for i := 0; i < 5; i++ {
          fmt.Println(i)
      }
      

      В этом условии мы указываем, что пока i меньше 5, цикл будет продолжать работу.

      А в конце мы получаем пост-оператор:

      for i := 0; i < 5; i++ {
          fmt.Println(i)
      }
      

      В этой части мы инкрементируем значение переменной i на 1 каждый раз после каждой итерации с помощью оператора инкремента i++.

      При запуске этой программы вывод выглядит следующим образом:

      Output

      0 1 2 3 4

      Цикл отработал 5 раз. Первоначально он задает для i значение 0, а затем проверяет, является ли значение i меньше 5. Так как значение i меньше 5, цикл выполняется и функция fmt.Println(i) исполняется. После завершения цикла вызывается оператор i++, а значение i увеличивается на 1.

      Примечание. Необходимо помнить, что в программировании мы обычно начинаем индексы с 0, поэтому хотя было выведено 5 чисел, они варьируются в диапазоне от 0 до 4.

      Мы не обязательно должны начинать с 0 или заканчивать заданным значением. Мы можем присвоить любое значение для нашего инициирующего оператора и останавливать работу цикла на любом значении пост-оператора. Это позволяет нам создавать желаемый диапазон для работы цикла:

      for i := 20; i < 25; i++ {
          fmt.Println(i)
      }
      

      Здесь итерация выполняется с 20 (включая) до 25 (не включая), поэтому вывод выглядит следующим образом:

      Output

      20 21 22 23 24

      Также мы можем использовать наш пост-оператор для инкрементирования на различных значениях. Это аналогично шагу в других языках:

      Сначала давайте воспользуемся пост-оператором с положительным значением:

      for i := 0; i < 15; i += 3 {
          fmt.Println(i)
      }
      

      В данном случае цикл for задан таким образом, чтобы выводить числа с 0 до 15, но с увеличением на 3, так что на экран будет выводиться только каждое 3 число:

      Output

      0 3 6 9 12

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

      for i := 100; i > 0; i -= 10 {
          fmt.Println(i)
      }
      

      Здесь мы зададим для i начальное значение 100, воспользуемся условием i < 0 для остановки при 0, а в пост-операторе будем уменьшать значение на 10 с помощью оператора -=. Цикл начинает работу при 100 и заканчивается при 0, а значение уменьшается на 10 при каждой итерации. Вы можете увидеть, как это происходит, в выводе:

      Output

      100 90 80 70 60 50 40 30 20 10

      Также вы можете исключить инициирующий оператор и пост-оператор из синтаксиса for и использовать только условие. Это так называемый цикл с условием:

      i := 0
      for i < 5 {
          fmt.Println(i)
          i++
      }
      

      На этот раз мы объявили переменную i отдельно от цикла for в предшествующей строке кода. Цикл имеет только одно условие, которое проверяет, остается ли i менее 5. Если условие возвращает true, цикл будет продолжаться.

      Иногда вы можете не знать количество итераций, которое вам потребуется для выполнения определенной задачи. В этом случае вы можете пропустить все операторы и использовать ключевое слово break для прекращения цикла:

      for {
          if someCondition {
              break
          }
          // do action here
      }
      

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

      buffer.go

      package main
      
      import (
          "bytes"
          "fmt"
          "io"
      )
      
      func main() {
          buf := bytes.NewBufferString("onentwonthreenfourn")
      
          for {
              line, err := buf.ReadString('n')
              if err != nil {
                  if err == io.EOF {
      
                      fmt.Print(line)
                      break
                  }
                  fmt.Println(err)
                  break
              }
              fmt.Print(line)
          }
      }
      

      В предыдущем коде buf :=bytes.NewBufferString("onentwonthreenfourn") объявляет буфер с некоторыми данными. Поскольку мы не знаем, когда буфер завершит чтение, мы создадим цикл for без условия. Внутри цикла for мы используем строку line, err := buf.ReadString('n') для считывания строки из буфера и проверки на наличие ошибок при чтении из буфера. Если произошла ошибка, мы устраняем ее и используем ключевое слово break для выхода из цикла. С этими точками break вам не нужно добавлять условие, чтобы остановить цикл.

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

      Прохождение циклом по последовательным типам данных с помощью RangeClause

      В Go часто используются циклы for для прохождения по элементам последовательных типов данных или коллекций, например, срезов, массивов и строк. Чтобы облегчить этот процесс, мы можем использовать цикл for с синтаксисом RangeClause. Хотя вы можете пройтись по последовательным типам данных с помощью синтаксиса ForClause, RangeClause понятнее и его удобнее читать.

      Прежде чем переходить к использованию RangeClause, давайте рассмотрим, как мы можем пройтись по элементам среза с помощью синтаксиса ForClause:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for i := 0; i < len(sharks); i++ {
              fmt.Println(sharks[i])
          }
      }
      

      В результате вы получите следующий вывод, содержащий каждый элемент среза:

      Output

      hammerhead great white dogfish frilled bullhead requiem

      Теперь давайте воспользуемся RangeClause для выполнения того же набора действий:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for i, shark := range sharks {
              fmt.Println(i, shark)
          }
      }
      

      В данном случае выводим каждый элемент из списка. Хотя мы использовали переменные i и shark, мы могли вызвать любую переменную с действительным именем переменной и получить тот же результат:

      Output

      0 hammerhead 1 great white 2 dogfish 3 frilled 4 bullhead 5 requiem

      При использовании range для среза всегда будут возвращаться два значения. Первое значение будет индексом, в котором находится текущая итерация цикла, а второе — это значение, скрывающееся в элементе с данным индексом. В данном случае для первой итерации индекс был 0, а значение — hammerhead.

      Иногда нам требуется только значение внутри элементов среза, а не индекс. Если мы изменим предыдущий код, чтобы выводить только значение, то получим ошибку компиляции:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for i, shark := range sharks {
              fmt.Println(shark)
          }
      }
      

      Output

      src/range-error.go:8:6: i declared and not used

      Поскольку i объявляется внутри цикла for, но не используется ни разу, компилятор вернет ошибку i declared and not used. Такая же ошибка может быть получена в Go при любом объявлении переменной, которая не будет использована.

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

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for _, shark := range sharks {
              fmt.Println(shark)
          }
      }
      

      Output

      hammerhead great white dogfish frilled bullhead requiem

      Этот вывод показывает, что цикл for проходит по срезу строк и выводит каждую строку из среза без индекса.

      Также вы можете использовать range для добавления элементов в список:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}
      
          for range sharks {
              sharks = append(sharks, "shark")
          }
      
          fmt.Printf("%qn", sharks)
      }
      

      Output

      ['hammerhead', 'great white', 'dogfish', 'frilled', 'bullhead', 'requiem', 'shark', 'shark', 'shark', 'shark', 'shark', 'shark']

      Здесь мы добавили заполнитель в виде строки "shark"для каждого элемента длины среза sharks.

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

      Также мы можем использовать оператор range для заполнения среза значениями:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          integers := make([]int, 10)
          fmt.Println(integers)
      
          for i := range integers {
              integers[i] = i
          }
      
          fmt.Println(integers)
      }
      

      В данном примере срез integers инициализируется с десятью пустыми значениями, но цикл for задает все значения в списке, например:

      Output

      [0 0 0 0 0 0 0 0 0 0] [0 1 2 3 4 5 6 7 8 9]

      Первый раз, когда мы выводили значение среза integers, то видели только нули. Затем мы проходим по каждому индексу и задаем значение для элемента с текущим индексом. Далее мы выводим значения integers второй раз, демонстрируя, что все они имеют значения от 0 до 9.

      Также мы можем использовать оператор range для прохождения по каждому символу в строке:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sammy := "Sammy"
      
          for _, letter := range sammy {
              fmt.Printf("%cn", letter)
          }
      }
      

      Output

      S a m m y

      При прохождении по map оператор range будет возвращать ключ и значение:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          sammyShark := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}
      
          for key, value := range sammyShark {
              fmt.Println(key + ": " + value)
          }
      }
      

      Output

      color: blue location: ocean name: Sammy animal: shark

      Примечание. Важно отметить, что порядок, в котором map возвращает значения, является случайным. Каждый раз, когда вы запускаете эту программу, вы можете получить разный результат.

      Теперь, когда мы научились проходиться по последовательным данным с помощью range для циклов for, давайте посмотрим, как можно использовать циклы внутри циклов.

      Вложенные циклы

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

      Вложенные циклы структурно похожи на вложенные операторы if. Они построены следующим образом:

      for {
          [Action]
          for {
              [Action]  
          }
      }
      

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

      Давайте реализуем вложенный цикл for, чтобы мы более внимательно изучили этот вопрос. В данном примере внешний цикл будет проходить по срезу с целыми числами numList, а внутренний цикл будет проходить по срезу строк alphaList.

      main.go

      package main
      
      import "fmt"
      
      func main() {
          numList := []int{1, 2, 3}
          alphaList := []string{"a", "b", "c"}
      
          for _, i := range numList {
              fmt.Println(i)
              for _, letter := range alphaList {
                  fmt.Println(letter)
              }
          }
      }
      

      При запуске этой программы мы получим следующий вывод:

      Output

      1 a b c 2 a b c 3 a b c

      Вывод показывает, что программа завершает первую итерацию внешнего цикла, выводя 1, после чего запускается выполнение внутреннего цикла с выводом a, b и c соответственно. Когда внутренний цикл завершен, программа возвращается вверх внешнего цикла, выводит 2, а затем снова в полном объеме выводит внутренний цикл (a, b, c) и т. д.

      Вложенные циклы for могут быть полезными для итерации по элементам внутри срезов, состоящих из срезов. В срезе, состоящем из срезов, если мы используем только один цикл for, программа выведет каждый внутренний список как элемент:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          ints := [][]int{
              []int{0, 1, 2},
              []int{-1, -2, -3},
              []int{9, 8, 7},
          }
      
          for _, i := range ints {
              fmt.Println(i)
          }
      }
      

      Output

      [0 1 2] [-1 -2 -3] [9 8 7]

      Чтобы получить доступ к каждому элементу внутренних срезов, мы реализовали вложенный цикл for:

      main.go

      package main
      
      import "fmt"
      
      func main() {
          ints := [][]int{
              []int{0, 1, 2},
              []int{-1, -2, -3},
              []int{9, 8, 7},
          }
      
          for _, i := range ints {
              for _, j := range i {
                  fmt.Println(j)
              }
          }
      }
      

      Output

      0 1 2 -1 -2 -3 9 8 7

      Когда мы используем вложенный цикл for, мы можем пройтись по отдельным позициям внутри этих срезов.

      Заключение

      В этом обучающем руководстве мы узнали, как объявлять и использовать циклы for для решения повторяющихся задач в Go. Также мы узнали три разных способа использования цикла for и то, когда их можно использовать. Чтобы узнать больше о циклах for и о том, как контролировать их работу, прочитайте статью Использование операторов break и continue при работе с циклами в Go.



      Source link