GoLang
Вольный и расширенный перевод оригинального репозитория Go Cheat Sheet на русский язык.
Участники
Если вы нашли ошибку или хотите расширить список шпаргалок, а также знаете другие источники для изучения, сообщите о них, внеся изменения через Pull Requests.
Источники
Большинство примеров кода исходного репозитория взяты из официального тура по Go, который является прекрасным введением для знакомства с языком.
Вы также можете использовать онлайн компилятор на официальном сайте или развернуть собственную песочницу Better Go Playground для запуска и проверки блоков кода.
Описание языка
- Императивный язык, где описывается последовательность шагов (инструкций), которые необходимо выполнить для достижения результата. В отличии от декларативных языков, где описывается результат, который нужно получить, оставляя процесс выполнения скрытым (например, как в
SQL
илиHTML
). - Используется статическая типизация для проверка типов переменных во время компиляции. Это когда тип переменной не может быть изменен после его присвоения (например, как в
TypeScript
в отличии отJavaScript
). - Синтаксис похож на
C
(но меньше скобок и нет точек с запятой в конце каждой строки), а структура — наOberon-2
. - Компилируется в машинный код без использования промежуточных слоев (
Runtime
, например, какJVM
вJava
или.NET
вC#
), который должен быть установлен на машине для работы программы. - Нет классов, но есть структуры с методами.
- Не предоставляет подклассов, основанного на типах, но имеет возможность заимствовать части реализации, встраивая типы в структуру или интерфейс (embedding).
- Функции могут возвращать несколько значений и их можно присваивать переменным, так как они рассматриваются как объекты.
- Функции можно передавать в другие функции в качестве аргументов, а также функции могут возвращать другие функции как результат.
- Имеет замыкания (
closures
), которые позволяют функциям хранит и использовать переменные из внешней области видимости, даже если она выполняется в другом контексте (например, за пределами этой области). - Невозможно напрямую изменять значение указателя с помощью арифметических операций (например,
ptr++
). Это нужно, чтобы исключить возможные ошибки, такие как выход за пределы памяти или доступ к неправильным участкам памяти. - Встроенные примитивы параллелизма: горутины и каналы.
- Поддерживаются динамические и статические срезы (
slices
, аналог списков или массивов в других языках, где элементы хранятся в порядке их добавления и индексируются числами), а также карты (maps
, аналог словарей или хэш-таблиц, где содержится уникальный ключ и его значение).
Базовый синтаксис
Получить информацию о функции
go doc fmt.Println
package fmt // import "fmt"
func Println(a ...any) (n int, err error)
Println formats using the default formats for its operands and writes to
standard output. Spaces are always added between operands and a newline
is appended. It returns the number of bytes written and any write error
encountered.
Инициализация нового проекта:
mkdir test
cd test
go mod init test
# Windows
notepad main.go
# Linux
nano main.go
Вывод на экран (Print)
package main
import "fmt"
func main()
Запуск:
go run main.go
Выведет на экран:
Hello
你好, नमस्ते, Привет, ᎣᏏᏲ
"Hello" in Chinese is 你好 ('Ni Hao')\n
"Hello" in Hindi is नमस्ते ('Namaste')
Ввод с клавиатуры (Scan)
package main
import "fmt"
func main()
Операторы
Арифметика
Оператор | Описание |
---|---|
+ | сложение |
- | вычитание |
* | умножение |
/ | деление * |
% | деление, возвращающие только остаток |
& | побитовое и |
| | побитовое или |
^ | побитовое исключающее или * * |
&^ | очистить бит (и нет ) * * * |
<< | сдвиг влево * * * * |
>> | сдвиг вправо |
* Если оба операнда имеют целый тип (int
, int8
, int32
, int64
), результат также будет целым числом, при этом остаток отбрасывается. Если хотя бы один из операндов имеет тип с плавающей точкой (float32
, float64
), результат будет дробным числом.
* * Возвращает 0
, если биты двух операндов равны, или 1
, если биты двух операндов различны.
* * * Возвращает 0
, если соответствующий бит второго операнда равен 1
, или бит первого операнда (0
или 1
), если соответствующий бит второго операнда равен 0
.
* * * * Сдвигает все биты числа влево на указанное количество позиций (аналог умножения числа на 2
в степени количества сдвигов), а новые биты справа заполняются нулями.
Сравнение
Оператор | Описание |
---|---|
== | равно |
!= | не равно |
< | меньше |
<= | меньше или равно |
> | больше |
>= | больше или равно |
Логика
Оператор | Описание |
---|---|
&& | логическое и |
|| | логическое или |
! | логическое отрецание |
Другие
Оператор | Описание |
---|---|
& | указатель (адрес в памяти на переменную) |
* | разыменовать указатель |
<- | оператор отправки / получения |
Переменные
Тип указывается после идентификатора (названия переменной):
var foo int // объявление без инициализации значения
var foo int = 42 // объявление с инициализацией
var foo, bar int = 42, 1302 // объявить и инициализировать несколько переменных одновременно
var foo = 42 // объявление с инициализацией с пропуском типа данных
foo := 42 // сокращение при объявление переменной (ключевое слово var опущено, тип данных определяется автоматически, работает только внутри функций)
const constant = "Это константа, которая используется для хранения неизменяемых данных"
// iota можно использовать для увеличения числа, начиная с 0
const (
_ = iota
a
b
c = 1 << iota
d
)
fmt.Println(a, b) // 1 2 (0 - пропускается)
fmt.Println(c, d) // 8 16 (2^3, 2^4)
Область видимости
В разных лексических блоках возможно заново объявлять переменные с одинаковыми именами. Компилятор считывая ссылку на переменную, ищет ее объявление начиная с текущего блока и выше.
func main()
Функции
// Простая функция
func functionName()
// Функция с параметрами (тип идет после идентификаторов)
func functionName(param1 string, param2 int)
// Несколько параметров одного типа
func functionName(param1, param2 int)
// Объявление типа для возвращаемого значения (идет после скобок параметров или во вторых скобках, если значений несколько)
func functionName() int
// Может возвращать несколько значений одновременно
func returnMulti() (int, string)
var x, str = returnMulti()
// Возвращаем несколько именованных результатов
func returnMulti2() (n int, s string)
var x, str = returnMulti2()
func main()
Замыкания
// Дочерние функции могут получить доступ к переменным, объявленным в родительской функции
func scope() func() int
func main()
func outer() (func() int, int)
func main()
Вариативные функции
Вариативная функция работает и вызывается как любая другая функция, за исключением того, что в нее возможно передать произвольное количество аргументов, используя ...
перед типом данных указанного параметра.
package main
import "fmt"
// Функция принимаем любое количество аргументов с типом данных int и возвращяет 2 значения
func adder(args ...int) (int, int)
// Функция принимает любое количество аргументов с любым типом данных, используя пустой интерфейс interface{}
func other(args ...any)
func main()
Типы данных
bool // логический тип (принимает true или false)
string // строка (текст)
int int8 int16 int32 int64 // знаковые целые числа (signed integer), могут быть как положительными, так и отрицательными
uint uint8 uint16 uint32 uint64 uintptr // беззнаковые целые числа (unsigned integer), могут быть только положительными или равными нулю
byte // псевдоним для uint8 (диапазон значений от 0 до 255)
rune // псевдоним для типа int32, представляет собой кодовую точку (Unicode code point) - это число, соответствующее символу в стандарте Unicode
// В отличие от char в некоторых языках (например, C/C++), который обычно занимает 1 байт и хранит символы ASCII, rune занимает 4 байта
// и может хранить любой символ Unicode, включая буквы разных алфавитов, эмодзи и спецсимволы
float32 float64 // число с плавающей точкой одинарной и двойной точности
complex64 complex128 // комплексное число (1 + 2i или 3.14 + 4.2i), имеющие реальную и мнимую часть
interfae // универсальный тип, который может позволяет работать с переменными неизвестного или изменяющегося типа
Тип данных | Описание | Диапазон значений |
---|---|---|
uint8 | Беззнаковые 8-битные целые числа | от 0 до 255 |
uint16 | Беззнаковые 16-битные целые числа | от 0 до 65535 |
uint32 | Беззнаковые 32-битные целые числа | от 0 до 4294967295 |
uint64 | Беззнаковые 64-битные целые числа | от 0 до 18446744073709551615 |
int8 | Знаковые 8-битные целые числа | от -128 до 127 |
int16 | Знаковые 16-битные целые числа | от -32768 до 32767 |
int32 | Знаковые 32-битные целые числа | от -2147483648 до 2147483647 |
int64 | Знаковые 64-битные целые числа | от -9223372036854775808 до 9223372036854775807 |
Все предварительно объявленные идентификаторы Go
определены в пакете builtin.
Преобразование типов
var i int = 42
var f float64 = float64(i) // преобразуем тип данных int в float64
var u uint = uint(f) // преобразуем тип данных float64 в unit
// Альтернативный синтаксис
i := 42
f := float64(i)
u := uint(f)
Структуры управления
Условия if
func main()
Условия switch
После выполнения условия при использование переключателей, прерывания обрабатываются автоматически.
package main
import (
"fmt"
"os"
)
func main()
// Как в случае с "for" и "if", возможно иметь оператор присваивания перед значением switch
switch os := runtime.GOOS; os
// Возможно использовать сравнения
number := 42
switch
// Все случаи могут быть представлены в виде списков, разделенных запятыми
var char byte = '?'
switch char
Переключение типа
Переключение типа похоже на обычный оператор switch
, но в условиях указывается типы (а не значения), которые сравниваются с типом значения, содержащегося в данном значении интерфейса.
package main
import "fmt"
func do(i interface)
func main()
// Число 21 равно 42 по типу данных
// Значение "hello" равно 5 bytes
// Тип bool неизвестен
Циклы
В Go
используются только универсальные циклы for
, другие операторы (например, while
или until
) отсутствуют.
// Используется 9 интераций с 1 по 9 (до 10)
// for [инициализация счетчика]; [условие проверки счетчика для продолжение (если true) или остановки цикла]; [изменение счетчика]{
for i := 1; i < 10; i++
// Цикл (loop) - while
for ; i < 10;
// Если есть только условие, точки с запятой опускаются
for i < 10
// Если опустить условие, равноценно использованию бесконечного цикла while (true)
var i = 1
for
// Использование пропуска и прерывания в цикле
// Метка here (произвольное имя) позволяет указать целевой цикл, на который будут ссылаться операторы continue и break
here:
// Используем 2 интерации во внешнем цикле
for i := 0; i < 2; i++
// 1-я интерация: внешний цикл с значением i=0 в внутреннем цикле пропускает интерацию внешнего цикла, т.к. срабатывает условие i==0
// 2-я интерация: внешний цикл с значением i=1 в внутреннем цикле пропускает условие i==0
// Переменная j получает значение 2, которое печатается и завершает внутренний (текущий) цикл во втором условие
// Программа завершается, т.к. интерации внешнего цикла закончились
there:
for i := 0; i < 2; i++
// 1-я интерация внешнего цикла начинается с i=0, в внутреннем цикле j=1 пропускает первую интерацию
// 2-я интерация внутреннего цикла пропускает первое условие, печатает на экран текущее значение j=2 и во втором условие завершает внешний цикл
Примеры циклов
package main
import "fmt"
// Функция, возвращающая название месяца через условную конструкцию switch
func getMonthName(month int) string
// Второй вариант функции через классическое условие по индеку массива
func getMonthName2(month int) string
func main()
Типы последовательностей
Типы последовательностей представляют собой структуры данных, хранящие упорядоченные наборы значений.
Массивы (array)
Массив (статические срезы) - фиксированная по размеру последовательность элементов (arr[10]).
var a [10]int // объявить массив int длиной 10 (длина массива является частью типа)
a[3] = 42 // присвоить значение элементу, по его порядковому номеру
i := a[3] // прочитать элементы
// Возможные варианты объявление с инициализацией значений
var a = [2]int
// Массив из двух элементов: [1 2]
a := [2]int
// Многоточие используется компилятором для вычисления длины массива
a := [...]int
Срезы (slice)
Срез (динамические массивы) - это последовательность элементов одного типа с динамической структурой, которая может быть получена из массивов или других срезов с помощью операции среза (arr[start:end]). Срезы могут иметь явное указание длины и емкости, которые можно задать с помощью встроенный функции make
, например, чтобы инициализировать элементы среза нулевыми значениями или заранее выделить нужное количество памяти (количество элементов в срезе не ограничивается, но потребует выделения новой памяти).
package main
import "fmt"
func main()
Операции с срезами
Указатель — ссылается на первый элемент массива, доступный через срез (может не совпадать с началом самого массива).
Длина (length) — количество элементов в срезе.
Емкость (capacity) — общее количество элементов от начала среза до конца базового массива, на котором основан срез.
Если изменить значение в базовом массиве, то значение в дочернем срезе также изменится (или наоборот), т.к. элементы слайса и массива находятся в одном участке памяти. При создание среза на основе массива достаточной длины, возможно избежать операций выделения памяти при создании нового массива и копирования элементов из одного массива в другой.
package main
import (
"fmt"
)
func check(baseArray [10]int, baseSlice []int)
func main()
Диапазоны (range)
Диапазон используется для перебора индексов и элементов массива в цикле.
// Цикл по массиву/срезу
for i, e := range a
// Если нужен только элемент "e"
for _, e := range a
// Если нужен только индекс
for i := range a
Словари (map)
package main
import "fmt"
type Custom struct
func main()
Структуры
Вместо классов (class
) в Go
используются структуры (struct
), которые являются новым типом данных комбинированных значений, а также могут содержать методы. Поля структуры всегда инициализируются нулевыми значениями при ее объявлении.
package main
import (
"fmt"
)
// Определение структуры Vertex
type Vertex struct
// Создаем метод для переданной структуры, который может оперировать ее элементами
func () float64
// Мутирующий метод, изменяющий поля переданной структуры
// Метод получает указатель на структуру (тип *Vertex), а не копию структуры (тип Vertex)
func (n float64)
func main()
Пример использования структуры и перебор элементов в цикле.
package main
import "fmt"
type test struct
func main()
Анонимные структуры
В отличии от map[string]interface{}
, анонимные структуры имеют строгую типизацию, что уменьшает ошибки и повышает производительность, но его нельзя использовать в разных местах без дублирования объявления.
package main
import "fmt"
func main()
Указатели
Аргументы в функциях и методах всегда копируются, указатели позволяют работать напрямую с содержимым переданных переменных и структурами данных, без копирования их содержимого (изменяя оригинальную переменную).
Оператор &
используется для взятия адреса из памяти, а не значения самой переменной.
Функция new()
выделяет память для указанного типа и возвращает переменной указатель на него, в отличие от оператора &
, который возвращает указатель на существующую переменную.
package main
import (
"fmt"
)
func test(param *int)
func main()
p := Vertex // "p" - это структура Vertex
q := &p // "q" указывает на структуру Vertex
r := &Vertex // "r" также указывает на структуру Vertex
// Объявление переменной с указателем на структуру *Vertex
var s *Vertex = new(Vertex) // функция "new" создает указатель на новый экземпляр структуры с пустыми значениями &{0 0}
Интерфейсы
Интерфейс - это набор методов (требований), которые должен иметь тип, чтобы соответствовать этому интерфейсу.
// Создаем пустой интерфейс (принимает произвольное количество значений любого типа)
s := []interface
s = []any // []any{} это alias для []interface{}{}
fmt.Println(s) // [a 2 c 4 e]
fmt.Println(s...) // распаковываем: a 2 c 4 e
// Объявление интерфейса с одинм методом Awesomize(), который возвращает строку
type Awesomizer interface
// Обычная структура, которая может реализовывать методы
type Foo struct
// Добавление (реализация) метода Awesomize() в структуре Foo
// Тип автоматически соответствует интерфейсу, если он реализует все его методы
func () string
Встраивание
В Go
нет подклассов, вместо этого используется встраивание интерфейса и структуры, которое добавляет методы встроенной структуры к внешней.
// В структуру Server встраиваются все методы, которые есть у метода Logger из структуры log
type Server struct
// Структура Server инициализируется с помощью указателя на log.Logger
server := &Server
// Когда вызывается server.Log(...), Go автоматически перенаправляет вызов к server.Logger.Log(...).
server.Log(...)
// Поле встроенного типа доступно через его имя, по этому переменной можно присвоить ссылку на server.Logger
var logger *log.Logger = server.Logger
Обработка ошибок
Обработка исключений отсутствует. Вместо этого функции, которые могут выдать ошибку, просто объявляют дополнительное возвращаемое значение типа error (чаще всего вторым возвращаемым параметром).
Встроенный тип интерфейса error
— это общепринятый интерфейс для представления состояния ошибки, при этом нулевое значение не представляет ошибки.
type error interface
Пример:
package main
import (
"errors"
"fmt"
"math"
)
// Определение функции sqrt должно быть вне main
func sqrt(x float64) (float64, error)
func main()
Параллелизм
Горутины
Горутины — это легковесные потоки (управляемые Go
, а не потоками ОС).
go f(a, b)
запускает новую горутину, которая запускает f
(при условии, что f
— это функция).
// Просто функция (которая позже может быть запущена в горутине)
func doStuff(s string)
func main()
Синхронизация
Пакет sync
используется для ожидания завершения всех запущенных горутин.
package main
import (
"fmt"
"sync"
)
func doStuff(s string, wg *sync.WaitGroup)
func main()
Таймер
Таймеры из пакета time
используются для задержки (паузы) на указанное время:
package main
import (
"fmt"
"time"
)
func goRun()
func main()
Небуферизованный канал
Небуферизованный канал блокирует операцию записи, пока не будет выполнено чтение, и наоборот.
// Создаем небуферизованный канал типа "int"
ch := make(chan int)
// Отправляем значение 42 в канал "ch"
// Операция блокирует текущую горутину, пока другая горутина не прочитает его значение
ch <- 42
// Получаем значение из канала "ch"
// Это также блокирует выполнение, пока не будет доступно значение для чтения в канале
v := <-ch
Буферизованный канал
Буферизованный канал позволяет отправлять и получать данные без блокировки, пока размер буфера не будет превышен, как только буфер заполняется, запись блокируется, пока другие горутины не начнут извлекать значения из канала.
Закрытие канала — это сигнал получателю, что больше значений не будет отправляться в канал, при этом отправленные в него данные не удаляются. Это необходимо для того, чтобы получатели знали, что можно завершить чтение. Закрытие канала происходило только в той горутине, которая отправляет данные.
package main
import "fmt"
func main()
Вывод: 0 1 2 3 4 5 6 7 8 9 Канал закрыт, данные не доступны
Селекторы
Оператор select
работает как многоканальный оператор switch
. Выбор блоков в операциях с несколькими каналами, если один из них разблокируется, выполняется соответствующие условие. Он блокируется до тех пор, пока одно из выражений case
не будет готов к выполнению, при этом остальные игнорируются.
package main
import (
"fmt"
"time"
)
func doStuff(channelOut, channelIn chan int)
func main()
Аксиомы канала
Отправка в пустой канал блокируется навсегда и вызывает фатальную ошибку:
var c chan string
c <- "Hello, World!"
Чтение из нулевого канала блокируется навсегда:
var c chan string
fmt.Println(<-c)
Отправка в закрытый канал вызывает панику:
var c = make(chan string, 1)
c <- "Hello, World!"
close(c)
c <- "Hello, Panic!"
Прием из закрытого канала немедленно возвращает нулевое значение:
var c = make(chan int, 2)
c <- 1
c <- 2
close(c)
for i := 0; i < 3; i++
// 1 2 0
Примеры каналов и горутин
package main
import (
"fmt"
"time"
"sync"
)
func goRun(ch chan string)
func goRunThree(ch chan string)
func printMessage(msg string, wg *sync.WaitGroup)
func main()
Форматированный вывод (printf)
Формат | Описание |
---|---|
%T | вывод типа данных переменной |
%p | вывод значения указателя (адрес в памяти, в шестнадцатеричном виде) |
%v | универсальный спецификатор, для типа boolean (аналогичен %t ), целочисленных типов (%d ), чисел с плавающей точкой - %g , строк - %s |
%#v | вывод значения (структуру, срез, карту или другой тип) в виде Go-литерала (как его можно было бы записать в исходном коде Go) для отладки |
%t | вывод значений типа boolean (true или false ) |
%s | вывод строки (string ) |
%f | вывод чисел с плавающей точкой (float32 или float64 ) |
%5f | ширина значения (если значение меньше ширины, то остаток заполняется пробелами) |
%.2f | точность остатока (выводит 2 цифры в дробной части после точки) |
%d | вывод целых чисел в десятичной системе |
%o | вывод целых чисел в восьмеричной системе |
%b | вывод целых чисел в двоичной системе |
%c | вывод символов, представленных числовым кодом (тип данных rune или byte ) в формате их числовых/буквенных значений |
%q | вывод символов в одинарных кавычках (тип данных rune или byte в формате кодового значения Unicode) |
%x | вывод целых чисел в шестнадцатеричной системе, буквенные символы числа имеют нижний регистр a-f |
%X | вывод целых чисел в шестнадцатеричной системе, буквенные символы числа имеют верхний регистр A-F |
%U | вывод символов в формате кодов Unicode, например, U+1234 |
%e | вывод чисел с плавающей точкой в экспоненциальном представлении, например, -1.234456e+78 |
%E | тоже самое что %e но в верхнем регистре, например, -1.234456E+78 |
package main
import (
"fmt"
)
func main()
// 'A' 1 '1' "123"
// 123 123 true 1.2
// "100.12"
Строки (strings)
package main
import "fmt"
func main()
Функции для работы со строками из пакета strings
:
package main
import (
"fmt"
"strings"
)
func main()
Регулярные выражения (regexp)
Основные элементы синтаксиса регулярных выражений:
Символ | Описание |
---|---|
. | любой символ, кроме символа новой строки |
* | 0 или более повторений |
+ | 1 или более повторений |
{n} | точно n повторений (например, a{3} , соответствует: "aaa" ) |
{n,} | минимум n повторений (например, a{2,} , соответствует: "aa" , "aaa" и т.д.) |
{n,m} | от n до m повторений (например, a{2,4} , соответствует: "aa" , "aaa" , "aaaa" ) |
? | 0 или 1 повторений |
^ | начало строки |
$ | конец строки |
[] | группа символов (например, [a-z] ) |
\s | любой пробельный символ (пробел, табуляция, новая строка и другие пробельные символы) |
\d | цифра (эквивалентно [0-9] ) |
\D | любой символ, не являющийся цифрой (эквивалентно [^0-9] ) |
\w | буквенно-цифровой символ (буквы, цифры и подчеркивание, эквивалентно [a-zA-Z0-9_] ) |
\W | не буквенно-цифровой символ (эквивалентно [^a-zA-Z0-9_] ) |
\b | граница слова (например, \bword\b соответствует "word" , и не подхоит "wordy" ) |
(?i) | делает выражение нечувствительным к регистру |
\ | экранирование специальных символов |
() | группа захвата |
| | логическое ИЛИ (например, `a |
Основные функции пакета regexp
:
regexp.MatchString
— проверяет, соответствует ли строка регулярному выражению.
package main
import (
"fmt"
"regexp"
)
func main()
regexp.Compile
— компилирует регулярное выражение и возвращает объект типа*regexp.Regexp
, если выражение корректное, или возвращается ошибка.
package main
import (
"fmt"
"regexp"
)
func main()
regexp.FindAllString
— находит все подстроки в строке, которые соответствуют регулярному выражению, и возвращает их в виде среза строк.
package main
import (
"fmt"
"regexp"
)
func main()
regexp.ReplaceAllString
— заменяет все соответствующие части строки.
package main
import (
"fmt"
"regexp"
)
func main()
- Группы захвата
package main
import (
"fmt"
"regexp"
)
func main()
- Извлечение логина и домена из почтовых адресов
package main
import (
"fmt"
"regexp"
)
func main()
Математические вычисления
package main
import (
"fmt"
"math"
)
func customCeil(numerator int, denominator int) int
func main()
Встроенные пакеты
- Декларация пакета (объявление через
import
) производится в начале каждого исходного файла. - Исполняемые файлы находятся в пакете
main
. - Имя пакета соответствует последнему имени в пути импорта (например,
math/rand
- пакетrand
). - Идентификатор функции в верхнем регистре является экспортируемый (доступны из других пакетов).
- Идентификатор функции в нижнем регистре является частный (недоступны из других пакетов).
Встраивание файлов
Программы Go
могут встраивать статические файлы с помощью пакета embed
и директиву go:embed path/filename
:
package main
import (
"embed"
"fmt"
"io"
"log"
"net/http"
)
var content embed.FS
func main()
// Имитация реальных файлов с их содержимым для запуска в Playground
-- static/a.txt --
hello a
-- static/b.txt --
hello b
HTTP сервер
Реализация простого API
сервера на базе встроенной библиотеки net/http
:
package main
import (
"encoding/json"
"fmt"
"net/http"
)
// Обработчик API
func apiHandler(w http.ResponseWriter, r *http.Request)
func main()
Делаем запрос к API
через curl
:
| | |
HTTP клиент
Делаем запрос к API
в Go
:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main()
HTTP
запрос к API
для получения последней версии релиза указаного репозитория в GitHub:
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
// Формируем структуру ответа от API
type GitHubRelease struct
func main()
go run main.go
Вызов системных команд
Проверка доступности всех хостов в указанной подсети (асинхронный ICMP
опрос):
package main
import (
"fmt"
"os"
"os/exec"
"strings"
"sync"
)
func pingHost(ip string, wg *sync.WaitGroup)
func main()
go run main.go 192.168.3.0