/masteringGo

Разбор всех примеров книги Цукалоса - Mastering Go

Primary LanguageGoMIT LicenseMIT

Mastering-Go

Go и операционная система (ch01)

  • Пишем в файл (логи)
    customLog

  • Использование внешнего пакета

    go get -v github.com/mactsouk/go/simpleGitHub


Загруженные файлы пакета: ~/go/src/github.com/mactsouk/go/simpleGitHub/

Скомпилированные файлы пакета: ~/go/pkg/darwin_amd64/github.com/mactsouk/go/simpleGitHub.a
getPackage

Стандартные потоки UNIX: stdin, stdout и stderr
  • Стандартный поток вывода
    пишем в STDOUT
    stdOUT

  • Получение данных от пользователя
    читаем STDIN stdIN

  • Работа с аргументами командной строки читаем float из STDIN
    cla

  • Вывод ошибок в STDERR
    можно перенаправить поток вывода ошибок в файл stdERR

Запись в журнальные файлы, Логирование
debug
info
notice 
warning
err
critical
alert
emerg
  • Пишем в системный LogFile
    logFiles

  • Пишем в системный LogFatal
    logFatal

  • Пишем в системный LogPanic
    logPanic

  • Эмулируем свой Error
    newError

Go изнутри (ch02)

  • defer (стек наглядно)
    defer

  • Смотрим затраты памяти
    gColl

  • Некоторые переменные окружения (системные)
    goEnv

  • Простая Panic
    justPanic

  • Интересная разбивка Map через % остаток
    mapSplit

  • Пакет Unsafe - получаем адрес Pointer и размер
    moreUnsafe

  • panic() recover()
    panicRecover

  • Получаем число из строки (Atoi)
    requiredVersion

  • Инфрмация о текущей среде Go (пакет runtime)
    goEnv
    requiredVersion

Работа с основными типами данных (ch03)

  • Примеры цикла for
    loops

  • Массивы (многомерные) и итерация по ним
    usingArrays

  • Слайсы, копирование, make()
    slices
    reslice

  • Длина и вместимость Слайса
    lenCap

  • Функция copy() для Слайсов
    copySlice

  • Сортировка Слайса sort.Slice()
    sortSlice

  • Добавление существующего Массива к существующему Слайсу
    appendArrayToSlice

  • Хэш таблицы (map), создание, удаление, итерация
    usingMaps

  • Запись в хеш таблицу со значением nil невозможно
    failMap

  • Константы, генератор констант Iota
    constants

  • Указатели, создание, разыменование
    pointers

  • Время и дата, примеры использования
    usingMaps

  • Парсинг времени
    parseTime

  • Парсинг даты
    parseDate

  • Изменение формата даты и времени
    timeDate

  • Замер времени выполнения программы
    execTime

Использованеи составных типов данных (ch04)

Структуры
  • Структуры, разные способы создания
    structures

  • Создание Указателя на Структуру
    pointerStruct

  • Кортежи, возврат нескоьких значений
    tuples

RegExp
  • RegExp, чтение файла построчно, нахождение подстроки
    selectColumn

  • RegExp, сопоставление даты и времени
    changeDT

  • RegExp, проверка IPv4-адресов
    findIPv4

Строки
  • Создание строки, итерация
    strings

  • Руны (строка - множество рун)
    runes

  • Какие символы являются рунами (пакет unicode)
    unicode

  • Манипуляция строками (пакет string)
    useStrings

  • switch, string + RegExp
    switch

  • Хранилище Key:Value. В цикле слушаем StdIn и выполняем комманды
    keyValue

JSON
  • Читаем JSON из файла и Декодируем во вложенные структуры
    readJSON

  • Пишем наши структуры в виде JSON в файл
    writeJSON

  • функции Marshal() и Unmarshal() (удобнее чем encode/decode)
    сmUJSON

  • Чтение и запись JSON без структурирования (используется Map)
    parsingJSON

XML
  • Структуру переводим в XML
    rwXML

  • Чтение XML-файла
    readXML

  • Поля структуры как XML данные
    modXML

Структуры данных (ch05)

Пакет Container
  • Сontainer/heap (реализация интерфейса кучи)
    conHeap

  • Container/list (список)
    conList

  • Container/ring (Кольцо)
    conRing

Генерация чисел и строк
  • Генерация случайных чисел
    randomNumbers

  • Генерация случайных строк
    generatePassword

  • Генерация безопасной последовательности случайных чисел
    cryptoRand

Выполнение матричных вычислений
  • Сложение, вычитание матриц
    addMat

  • Умножение матриц
    mulMat

  • Деление матриц
    divMat

  • Как определить размер массива
    dimensions

  • Разгадывание Судоку
    sudoku

Неочевидные знания о пакетах и функциях Go (ch06)

Функции
  • Функции которые возвращают несколько значений
    functions

  • Функции, возвращающие именованные значения
    returnNames

  • Функции, принимающие указатели
    ptrFun

  • Функции, которые возвращают указатели
    returnPtr

  • Функции, которые возвращают другие функции
    returnFunction

  • Функции, которые принимают другие функции в качестве параметров
    funFun

  • Функции с переменным числом параметров
    variadic

Разработка Go-пакетов
  • Создание и использование пакета
    aPackage
    useAPackage
    Install:

    mkdir ~/go/src/aPackage
    cp aPackage.go ~/go/src/aPackage/
    go install aPackage

    Compile:

    go tool compile aPackage.go

  • Функция init()
    a
    b
    manyInit
    Install:

    mkdir ~/go/src/a
    cp a.go ~/go/src/a/
    go install a
    mkdir ~/go/src/b
    cp b.go ~/go/src/b/
    go install b

Модули
  • Читаем книгу (стр.290)
Некоторые пакеты Go (scanner/parser/token/ast)
  • Пакет syscall
    useSyscall

  • Встроенный пакет go/scanner (синтаксический сканер программы на Go)
    goScanner

  • Встроенный пакет go/parser (синтаксический анализ программы на Go)
    goParser

  • Парсим файл Go, подсчитываем кол-во яз.конструкций var
    varTimes

  • Поиск имен переменных заданной длины (сложно, куча вложенных if)
    varSize

Шаблонизатор для текста, HTML

Рефлексия и интерфейсы на все случае жизни (ch07)

Свои типы, интерфейсы и проверка типа
  • Создаём структуру (тип) и метод к ней
    methods

  • Проверка типа
    assertion

  • Создание интерфейс / использование интерфейса
    myInterface
    useInterface

  • Switch для типов данных
    switch

Рефлексия
  • Простой пример
    reflection

  • Более сложный пример
    advRefl

  • Библиотека reflectwalk (рефлексия)
    walkRef

ООП (композиция)

Как объяснить UNIX-системе, что она должна делать (ch08)

Аргументы командной строки
Интерфейсы io.Reader и io.Writer (Чтение / Запись в файл)
  • Построчное чтение текстового файла (пакет bufio)
    byLine

  • Чтение текстового файла по словам (пакет bufio, regexp)
    byWord

  • Чтение текстового файла по символам
    byCharacter

  • Чтение бинарных данных из /dev/random (пакет encoding/binary)
    devRandom

  • Чтение заданного кол-ва данных
    readSize

  • Чтение CSV файла и создание PNG
    CSVplot

  • Запись в файл (несколько способов)
    save

  • Загрузка и сохранение данных на диске
    CRUD
    сереализация - encoding/gob
    kvSaveLoad

  • Пакет strings - ввод и вывод данных в файл
    str

  • Пакет bytes
    сохранение в буфер bytes.Buffer
    работа с байтовыми срезами
    bytes

  • Полномочия доступа к файлам
    смотрим доступы к файлу
    permissions

  • Обработка сигналов в UNIX
    пакет os/signal
    обрабатываем сигналы передавая их в процесс
    handleTwo

  • Обработка всех сигналов системы
    так же передаём сигналы в процесс
    handleAll

  • Реализация утилиты cat(1) на Go
    вывод содержимого файла в стандартный поток вывода
    cat

  • Структура syscall.PtraceRegs
    вызов внешней команды для дочерних процессов
    ptraceRegs

  • Отслеживание системных вызовов
    traceSyscall

  • Идентификаторы пользователя и группы
    пакеты os, os/user
    находим id пользователя системы и групп к которой принадлежит пользователь
    ids

Конкурентность в Go: горутины, каналы, и конвейеры (ch09)

Горутины
  • Создание горутины
    simple

  • Создание нескольких горутин
    create

  • Как дождаться завершения горутин
    использование sync.WaitGroup
    кол-во Add() и Done() должно совпадать
    syncGo

Каналы
  • Запись в канал
    после закрытия канала горутина остановит своё выполнение
    writeCh

  • Чтение из канала
    вторая попытка чтения не выходит, так как канал уже закрыт
    readCh

  • Прием данных из закрытого канала
    что при чтении данных из закрытого канала возвращается нулевое значение соответствующего типа
    readClose

  • Каналы как аргументы функции
    func someFunc(out chan<- int64, in <-chan int64)

Конвейеры
  • Конвейер
    выходные данные одной горутины становятся входными данными для другой горутины
    для передачи данных используются каналы
    три горутины передают между собой данные
    в аргументах можно указать на запись или чтение канал, а сам канал может быть двусторонний
    pipeline
Сосотояние гонки
  • Выявление состояния гонки
    go run -race pipeline.go 1 10
    здесь есть общие переменные которые используют разные горутины
    pipeline

Конкурентность в Go: горутины, расширенные возможности (ch10)

  • Переменная среды GOMAXPROCS
    кол-во потоков которые могут одновременно выполняться
    по умолчанию равно кол-ву процессоров
    maxprocs

  • Ключевое слово select
    select похож на switch, но только для каналов
    можно запустить в цикле, тогда select будет работать пока не вызовим return
    select

  • Принудительное завершение горутины 1
    просто с помощью time.Sleep() или time.After()
    timeOut1

  • Принудительное завершение горутины 2
    с помощью sync.WaitGroup
    timeOut2

И снова о Go-каналах
  • Закрытие nil-channel вызовит panic
    var c chan string
    close(c)

  • Сигнальные каналы
    создаём последовательное выполнение горутин с помошью сигнальных каналов.
    defineOrder

  • Буферизованные каналы
    интересный пример с counter
    несколько значений в канале как бы в очереди на чтение
    bufChannel

  • Нулевые каналы
    Канал имеет значение nil
    nilChannel

  • Каналы каналов
    chSquare

  • Выбор последовательности исполнения горутин
    используются сигнальные каналы
    defineOrder

  • Как не надо использовать горутины
    наивный способ сортировки натуральных чисел с использованием горутин
    sillySort

Общая память и общие переменные (Mutex)
  • Тип sync.Mutex
    блокировка общих ресурсов для определенной горутины в момент исполлнения
    позволяет избежать состояние гонки (race)
    sync.Lock() и sync.Unlock()
    mutex

  • Что произойдет, если вы забудете разблокировать Mutex
    Locked!
    Fatal
    forgetMutex

  • Тип sync.RWMutex
    считается улучшенной версией Mutex
    разделение блокировки на чтение и запись, то есть читать могут сразу несколько горутин
    rwMutex

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

  • Совместное использование памяти с помощью горутин
    как можно организовать совместный доступ к данным с помощью выделенной для этого горутины
    monitor

И снова об операторе go
  • Closure variables в горутинах
    в такие переменные присваевается значение в момент фактического исполнения горутины
    то есть невозможно предсказать её значение
    cloGo
    cloGoCorrect
    endlessComp
Распознавание состояния гонки
  • Race
    гонка по данным происходит тогда, когда две или более инструкции обращаются к одному и тому же адресу памяти и хотя бы одна из них выполняет операцию записи.
    Если все операции являются чтением, то состояния гонки нет.
    Описывается как читать WARNING состояния гонки.

    $ go run -race raceC.go 10

    raceC
Пакет Context
  • Context
    можно передать значение в горутину или остановить её.
    simpleContext

  • Context - расширенный пример
    сделаем HTTP-клиент и зададим время ожидания ответа от сервера.
    useContext
    slowWWW

  • Context - ещё один пример
    используем context.TODO() вместо context.Background().
    Обе эти функции возвращают ненулевой пустой кон- текст, однако назначение у них разное.
    moreContext

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

Тестирование, оптимизация и профилирование кода (ch11)


Профилирование кода Go
  • Стандартный Go-пакет net/http/pprof
    этот пакет используется в случае профилирования веб-приложения (HTTP servers).

  • Простой пример профилирования
    Go поддерживает два вида профилирования - процессора и памяти.

    • Создаём файлы и записываем в них данные профилирования (используя пакет runtime/pprof):
      profileMe
    • Читаем данные профилирования с помощью утилиты pprof

      go tool pprof /tmp/cpuProfile.out


  • Удобный внешний пакет для профилирования
    github.com/pkg/profile

    go get github.com/pkg/profile

    Так же читаем данные профилирования с помощью утилиты pprof
    betterProfile

  • Пример профилирования с использованием веб-интерфейса
    чтобы пользовательский веб-интерфейс смог работать, необходимо установить Graphviz!
    Используем утилиту pprof

    go tool pprof -http=localhost:8080 /tmp/cpuProfile.out

  • Утилита go tool trace
    это средство просмотра файлов трассировки, которые можно сгенерировать одним из трех способов:

    • runtime/trace
    • net/http/pprof
    • go test -trace

    Генерируем отчёт и вызываем утилиту:
    goGC

    go tool trace /tmp/traceFile.out


Тестирование кода Go
  • Написание тестов для существующего кода Go
    testMe
    testMe_test

    go test testMe.go testMe_test.go


  • Тестовое покрытие кода
    codeCover
    codeCover_test

    go test -cover -v

    go tool cover -html=coverage.out


  • Тестирование HTTP-сервера с базой данных
    используем отдельную БД для тестирования.
    Тестируем запись и удаление значений в БД.
    webServer
    webServer_test

  • Пакет testing/quick
    Этот пакет генерирует случайные значения.
    randomBuiltin

  • Как быть, если тестирование выполняется слишком долго или вообще не заканчивается
    при вызове тестов указываем -timout too_long.go too_long_test.go

    go test too_long* -v -timeout 15s


Бенчмаркинг кода Go

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

  • Простой пример бенчмаркинга
    benchmarkMe
    benchmarkMe_test

    go test -bench=. benchmarkMe.go benchmarkMe_test.go

    go test -benchmem -bench=. benchmarkMe.go benchmarkMe_test.go


  • Неправильно определенные функции бенчмаркинга
    то из-за использования цикла for, при увеличении значения b.N время выполнения функции берчмаркинга также увеличивается.
    Это не позволяет функции BenchmarkFiboI() сойтись к какому-либо определенному числу,
    так что функция не завершается и, следовательно, не возвращает результат.

  • Бенчмаркинг буферизованной записи
    проверяем как размер буфера записи влияет на производительность всей операции записи.
    writingBU writingBU_test

  • Обнаружение недоступного кода Go
    cannotReach

    go vet cannotReach.go


  • Кросс-компиляция
    компиляция исходников под другую OS
    xCompile

    env GOOS=linux GOARCH=arm go build xCompile.go


  • Создание примеров функций
    примеры являются готовыми тестами, которые можно выполнить с помощью команды go test
    Используется сравнение вывода // Output:
    ex
    ex_test

  • От кода Go до машинного кода
    как код Go преобразуется в машинный код.
    machineCode

  • Использование ассемблера в Go
    как использовать ассемблер для реализации функций Go. add_me add_amd64

  • Генерация документации
    Go предоставляет инструмент godoc, который позволяет просматривать документацию пакетов — при условии,
    что в файлы включена дополнительная информация.

    mkdir ~/go/src/documentMe
    cp documentMe* ~/go/src/documentMe/
    ls -l ~/go/src/documentMe/

    documentMe
    documentMe_test

    godoc -http=":8080"


  • Использование образов Docker
    создаём образ Docker, содержащий базу данных PostgreSQL и код Go.

Основы сетевого программирования на Go (ch12)


Что такое net/http, net и http.RoundTripper
  • Тип http.Response
    описание объекта Response

  • Тип http.Request
    описание объекта Request

  • Тип http.Transport
    описание объекта Transport

Что такое TCP/IP

TCP расшифровывается как Transmission Control Protocol — протокол управления передачей.
Для передачи используются сегменты, которые называются TCP-пакетами.
TCP - это надежный протокол, который гарантирует, что пакет был доставлен.
Если доставка пакета не подтверждается, то TCP отправляет этот пакет повторно.
Пакет TCP также может использоваться для установления соединений, передачи данных, отправки подтверждений и закрытия соединений.

IP инкапсулирует данные, которые передаются по сети TCP/IP,
так как отвечает за доставку пакетов с исходного хоста на хост назначения в соответствии с IP-адресами.

Протокол UDP (User Datagram Protocol, протокол передачи датаграмм) основан на IP, следовательно, также ненадежен.
Протокол UDP проще, чем TCP.
UDP-сообщения могут быть потеряны, продублированы или доставлены не в должной последовательности.
Пакеты могут прибывать быстрее, чем получатель способен их обрабатывать.
UDP используется тогда, когда скорость важнее надежности.

  • Что такое IPv4 и IPv6
    IPv4 - 32 бита на адрес.
    IPv6 - 128 бит на адрес.

  • Утилита командной строки nc (netcat)
    Netcat можно применять в качестве TCP-клиента.

  • Чтение конфигурации сетевых интерфейсов
    Учимся считывать конфигурацию сетевых интерфейсов UNIX-машины на Go.
    netConfig

  • Выполнение DNS-поиска
    DNS.go

  • Получение NS-записей домена
    NSrecords

  • Получение MX-записей домена
    MX-записи указывают на почтовые серверы (mail servers) домена.
    MXrecords

Создание веб-сервера на Go
  • Веб-сервер на Go
    www

  • Использование пакета atomic
    Счётчик всех клиентов
    atomWWW

  • Профилирование HTTP-сервера
    wwwProfile

  • Создание веб-сайта на Go
    приложение для хранения Key=Value данных.
    Используем templates.
    kvWeb home

  • HTTP-трассировка
    позволяет поэтапно отслеживать прохождение HTTP-запроса.
    Используем пакет пакета net/http/ httptrace.
    httpTrace

  • Тестирование HTTP-обработчиков
    Грубо говоря тестируем ответы сервера (роуты).
    testWWW
    testWWW_test

Создание веб-клиента на Go

Задержки HTTP-соединений

Можно обойтись и без Context.

  • Http-задержка
    используем http.Transport{ Dial: Timeout, } clientTimeOut

  • Подробнее о SetDeadline
    Функция SetDeadline() используется в пакете net для того, чтобы задать максимальную
    длительность операций чтения и записи для данного сетевого соединения.

  • Установка периода ожидания на стороне сервера
    serverTimeOut

  • Еще один способ определить период ожидания
    anotherTimeOut


Инструменты Wireshark и tshark

Это инструменты для анализа сетевого трафика.

Go и gRPC

Процесс, который здесь описан, состоит из трех этапов
— создание файла описания интерфейса
— разработка клиента gRPC
— разработка сервера gRPC, который будет работать с клиентом gRPC.

  • Определение файла описания интерфейса

    brew install protobuf
    go get -u github.com/golang/protobuf/protoc-gen-go export PATH=$PATH:~/go/bin

    api.proto

    protoc -I . --go_out=plugins=grpc:. api.proto

    api.pb

  • gRPC-клиент
    gClient

  • gRPC-сервер
    gServer

Сетевое программирование: создание серверов и клиентов (ch13)


Работа с HTTPS-трафиком

По умолчанию для HTTPS номер TCP-порта — 443.

  • Создание сертификатов
    Cертификат для server:

    openssl genrsa -out server.key 2048
    openssl ecparam -genkey -name secp384r1 -out server.key
    openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650

    Сертификат для client:

    openssl req -x509 -nodes -newkey rsa:2048 -keyout client.key -out


  • HTTPS-клиент
    создаём HTTPS-клиент используя TLSClientConfig. httpsClient

  • Простой HTTPS-сервер
    https

  • Разработка TLS-сервера и TLS-клиента
    используем пакеты "crypto/tls" и "crypto/x509.
    Используем параметр InsecureSkipVerify: true.
    TLSserver
    TLSclient

Стандартный Go-пакет net

Чтобы создать на Go TCP- или UDP-клиент либо сервер, необходимо использовать функции, предлагаемые пакетом net.

  • TCP-клиент
    net.Dial()
    TCPclient

  • Другая версия TCP-клиента
    net.DialTCP()
    otherTCPclient

  • TCP-сервер
    net.Listen()
    TCPserver

  • Другая версия TCP-сервера
    net.ListenTCP()
    otherTCPserver

  • UDP-клиент
    net.DialUDP()
    UDPclient

  • Разработка UDP-сервера
    net.ListenUDP()
    UDPserver

Конкурентный TCP-сервер

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

  • Конкурентный TCP-сервер
    fiboTCP

  • Удобный конкурентный TCP-сервер
    реализуем Key = Value TCP хранилище.
    kvTCP

  • Создание образа Docker для TCP/IP-сервера на Go
    пример создания своего images.

  • RPC-клиент
    описываем сначала Interface в котором должно быть описание RPC методов сервера.
    Потом реализуем Server и Client импортировав туда описанный интерфейс.
    rpc.Dial()
    c.Call("MyInterface.Multiply", args, &reply)
    RPCclient

  • RPC-сервер
    rpc.Register(myInterface)
    RPCserver
    sharedRPC

  • Низкоуровневое сетевое программирование
    Смотрим содержимое пакетов.
    lowLevel

  • Получение необработанных сетевых данных ICMP
    syscallNet

Машинное обучение на Go (Ch14)

  • Вычисление простых статистических показателей
    stats

Регрессия

  • Реализация линейной регрессии
    regression

  • Вывод данных
    plotLR

Классификация

Кластеризация

  • Кластеризация
    cluster

Выявление аномалий

  • Выявление аномалий
    anomaly

Нейронные сети

  • Нейронные сети
    neural

Анализ выбросов

  • Анализ выбросов
    outlier

Работа с TensorFlow

TensorFlow — известная платформа с открытым исходным кодом, предназначенная для машинного обучения.

Поговорим о Kafka