Наша программа началась с package main с чего начнутся файлы в fmt package
Вместо того, чтобы каждый раз писать всё с нуля, реальный мир программирования требует от нас умения взаимодействовать с уже существующими библиотеками. В этой главе мы рассмотрим самые часто используемые пакеты, включенные в Go.
Предупреждаю: некоторые библиотеки достаточно очевидны (или были объяснены в предыдущих главах), многие из библиотек, включённых в Go требуют специальных знаний (например: криптография). Объяснение этих технологий выходит за рамки этой книги.
Строки
Go содержит большое количество функций для работы со строками в пакете strings :
Иногда нам понадобится работать с бинарными данными. Чтобы преобразовать строку в набор байт (и наоборот), выполните следующие действия:
Ввод / Вывод
Прежде чем мы перейдем к работе с файлами, нужно узнать про пакет io . Пакет io состоит из нескольких функций, но в основном, это интерфейсы, используемые в других пакетах. Два основных интерфейса — это Reader и Writer . Reader занимается чтением с помощью метода Read . Writer занимается записью с помощью метода Write . Многие функции принимают в качестве аргумента Reader или Writer . Например, пакет io содержит функцию Copy , которая копирует данные из Reader во Writer :
Чтобы прочитать или записать []byte или string , можно использовать структуру Buffer из пакета bytes :
Buffer не требует инициализации и поддерживает интерфейсы Reader и Writer . Вы можете конвертировать его в []byte вызвав buf.Bytes() . Если нужно только читать строки, можно так же использовать функцию strings.NewReader() , которая более эффективна, чем чтение в буфер.
Файлы и папки
Для открытия файла Go использует функцию Open из пакета os . Вот пример того, как прочитать файл и вывести его содержимое в консоль:
Мы используем defer file.Close() сразу после открытия файла, чтобы быть уверенным, что файл будет закрыт после выполнения функции. Чтение файлов является частым действием, так что вот самый короткий способ сделать это:
А вот так мы можем создать файл:
Чтобы получить содержимое каталога, мы используем тот же os.Open() , но передаём ему путь к каталогу вместо имени файла. Затем вызывается функция Readdir :
Иногда мы хотим рекурсивно обойти каталоги (прочитать содержимое текущего и всех вложенных каталогов). Это делается просто с помощью функции Walk , предоставляемой пакетом path/filepath :
Функция, передаваемая вторым аргументом, вызывается для каждого файла и каталога в корневом каталоге (в данном случае).
Ошибки
Контейнеры и сортировки
В дополнение к спискам и картам, Go предоставляет еще несколько видов коллекций, доступных в пакете container . В качестве примера рассмотрим container/list .
Список
Пакет container/list реализует двусвязный список. Структура типа данных связного списка выглядит следующим образом:
Каждый узел списка содержит значение (в нашем случае: 1, 2 или 3) и указатель на следующий узел. Но так как это двусвязный список, узел так же содержит указатель на предыдущий. Такой список может быть создан с помощью следующей программы:
Пустым значением List (вероятно, опечатка и имелось ввиду x — прим. пер.) является пустой список ( *List создаётся при вызове list.New ). Значения добавляются в список при помощи PushBack . Далее, мы перебираем каждый элемент в списке, получая ссылку на следующий, пока не достигнем nil .
Сортировка
Пакет sort содержит функции для сортировки произвольных данных. Есть несколько предопределённых функций (для срезов, целочисленных значений и чисел с плавающей точкой). Вот пример, как отсортировать ваши данные:
Хэши и криптография
Функция хэширования принимает набор данных и уменьшает его до фиксированного размера. Хэши используются в программировании повсеместно, начиная от поиска данных, заканчивая быстрым детектированием изменений. Хэш-функции в Go подразделяются на две категории: криптографические и некриптографические.
Некриптографические функции можно найти в пакете hash , который включает такие алгоритмы как adler32 , crc32 , crc64 и fnv . Вот пример использования crc32 :
Объект crc32 реализует интерфейс Writer , так что мы можем просто записать в него набор байт, как и в любой другой Writer . После записи мы вызываем Sum32() , который вернёт uint32 . Обычным применением crc32 является сравнение двух файлов. Если значение Sum32() для обоих файлов одинаковы, то, весьма вероятно (не со стопроцентной гарантией), содержимое этих файлов идентично. Если же значения отличаются, значит файлы, безусловно, разные:
Криптографические хэш-функции аналогичны их некриптографическим коллегам, однако у них есть одна особенность: их сложно обратить вспять. Очень сложно определить, что за набор данных содержится в криптографическом хэше, поэтому такие хэши часто используются в системах безопасности.
Одним из криптографических хэш-алгоритмов является SHA-1. Вот как можно его использовать:
Этот пример очень похож на пример использования crc32 , потому что оба они реализуют интерфейс hash.Hash . Основное отличие в том, что в то время как crc32 вычисляет 32-битный хэш, sha1 вычисляет 160-битный хэш. В Go нет встроенного типа для хранения 160-битного числа, поэтому мы используем вместо него срез размером 20 байт.
Серверы
На Go очень просто создавать сетевые серверы. Сначала давайте взглянем, как создать TCP сервер:
HandleFunc обрабатывает URL-маршрут ( /hello ) с помощью указанной функции. Мы так же можем обрабатывать статические файлы при помощи FileServer :
Пакеты net/rpc (remote procedure call — удаленный вызов процедур) и net/rpc/jsonrpc обеспечивают простоту вызова методов по сети (а не только из программы, в которой они используются).
run и myfile.go являются аргументами. Мы так же можем передать команде флаги:
Пакет flag позволяет анализировать аргументы и флаги, переданные нашей программе. Вот пример программы, которая генерирует число от 0 до 6. Но мы можем изменить максимальное значение, передав программе флаг -max=100 .
Любые дополнительные не-флаговые аргументы могут быть получены с помощью flag.Args() , которая вернет []string .
Синхронизация примитивов
Мьютексы
Мьютекс (или взаимная блокировка) единовременно блокирует часть кода в одном потоке, а так же используется для защиты общих ресурсов из не-атомарных операций. Вот пример использования мьютекса:
Когда мьютекс ( m ) заблокирован из одного процесса, любые попытки повторно блокировать его из других процессов приведут к блокировке самих процессов до тех пор, пока мьютекс не будет разблокирован. Следует проявлять большую осторожность при использовании мьютексов или примитивов синхронизации из пакета sync/atomic .
Традиционное многопоточное программирование является достаточно сложным: сделать ошибку просто, а обнаружить её трудно, поскольку она может зависеть от специфичных и редких обстоятельств. Одна из сильных сторон Go в том, что он предоставляет намного более простой и безопасный способ распараллеливания задач, чем потоки и блокировки.
Вопросы и обсуждения, связанные с программированием на языке Go.
- Конкурсные 0
- Неотвеченные
- Цитируемые
- Рейтинг
- Неотвеченные (мои метки)
Книги, документация, статьи и курсы по Go
Рекомендуемая литература, документация, статьи и курсы для изучения языка Go. Данный перечень входит в поддерживаемый сообществом Сборник учебных ресурсов по программированию.
Язык Go - зачем он нужен и что на нем пишут? [закрыт]
Этот язык уже несколько лет в поле видимости. Но что на нем пишут? И что можно написать? Стоит ли его учить? Или он скоро исчезнет?
Как в Go получить разность между двумя датами?
Есть ли в Go тернарный оператор?
Почему имена встроенных функций в Go набраны строчными буквами?
Функции и переменные с именами начинающимися со сточной буквы не видны снаружи пакета, так почему встроенные типы и функции начинаются со строчной буквы? Они описаны в пакете main?
Почему исполняемый файл Go много больше, чем C?
Go для масштабного веб-проекта
Здравствуйте. Хоть у меня вопрос по го, вкратце расскажу свой путь разработчика. Да, и еще, чтобы быть полностью откровенным упомяну: мне 16 лет. Программированием я заинтересовался в 9 лет, и с тех .
Проблемы с кодировкой при парсинге некоторых сайтов, Golang
Доброго времени суток. Столкнулся с такой проблемой: некоторые сайты парсятся адекватно - текст из формочек достается в читабельной кодировке, а некоторые - нет. Сначала грешил на UTF-8 на сайте, но .
Сравнение Go и Rust на алгоритме вычисления чисел Фибоначчи
Есть два кода реализующих один и тот же алгоритм: быстрое вычисления последовательности Фибоначчи. Алгоритм в оптимизации не нуждается. Программы работают примерно одинаково по скорости (до .
Golang и "concurrency"
На официальной русской страничке документации Golang сообщается: Термин "concurrency" в программировании, судя по всему, не имеет точного аналога в русском языке. Хотя многие переводят его .
В стандартной библиотеке database/sql нет возможности работать с событиями, как это обойти без cgo?
Я использую драйвер firebird. Появилась необходимость отслеживания событий в таблицах (insert, update). С удивлением обнаружил, что в выше упомянутом драйвере нет поддержки нотификации событий. В .
Golang загрузка больших файлов Google Drive
Есть задача загружать большие файлы (txt,docx,csv,xls) на Google Drive через API средствами с немедленной конвертацией в форматы Google языка Go, при реализации нашей программы выгрузки мы столкнулись .
Случайное число в golang
Как получить случайное число? Вот функция, но она выводить всегда цифру "81" package main import ("fmt"; "math/rand") func main() < fmt.Println(rand.Intn(100)) >
Получение значений переданных методом POST в Go
Подскажите, пожалуйста, как в Go собрать все значения, переданные программе методом POST? Примерно такой код: package main import "net/http" func main() < http.HandleFunc("/", handler) .
Как в golang использовать c или c++ код?
Подскажите простой пример использования функции из c \ c++ в программе на golang. Например на c \ c++ будет функция sayHello возвращающая значение - "Привет,Роман, это значение из функции" . Вот .
Вопросы и обсуждения, связанные с программированием на языке Go.
- Конкурсные 0
- Неотвеченные
- Цитируемые
- Рейтинг
- Неотвеченные (мои метки)
Как вернуть промежуточное значение?
Как вернуть status = 2, не прерывая цикл [и функцию]? package main import ( "fmt" "math/rand" "time" ) // Значения status: 1 - "успешно"; 2 - &.
json.Unmarshal не получается
Если от клиента из браузера xhr.send(j); получаю аяксом строку: j := `<"m": 1, "n": 3, "d": ["22032022", 12.59, 215]>` То не получается вынуть данные массива, ."m":>
Golang GORM "Has Many"
В следующем коде одному пользователю может принадлежать большое количество структур типа Pair<>, но при по пытке реализовать следующий код выходит ошибка: "повторяющееся значение ключа нарушает .
Работа с локальными модулями в go
Есть папка go в которой также есть две папки - greeting и hello greeting.go package greeting import "fmt" func Hello() < fmt.Println("Hello!") >func Hi() < fmt.Println(&.
Установка пакетов Golang
Как компилятор golang перебрасывает значение переменной в кучу?
Прочитал статью на хабре Языковая механика escape analysis но так и не понял один момент Когда компилятор компилирует проблему он должен переписывает вместо переменных адреса в памяти. Например вместо .
Как хранятся строки в golang?
Создаю несколько переменных подряд. Далее к одной переменной прибавляю произвольные данные и вижу что она осталась по своему же адресу. package main func main() < i := 5 println(&i) .
Использование структуры из другого пакета в методе
Всем привет. У меня есть несколько пакетов в проекте Пакет models содержит type User_JSON struct < UID string `json:"id"` Name string `json:"name"` Email string `.
не удается отпрофилировать сервер
Всем привет Есть такой код package main import ( "net/http" _ "net/http/pprof" "origin-api/controllers" "origin-api/getconf" "github.
Clean Code Architecture in Golang
Начал изучать реализацию Clean Code Architecture в Golang, и наткнулся на 2 варианта. Код в обоих выглядит одинаково, однако организация пакетов отличается. Выглядят они примерно так: Вопрос: Как все .
Наследование структур в Golang
Есть 2 структуры type parent struct < field1 string >type child struct < parent field2 int >на выходе получается type child struct < parent: parent< field1 string >field2 .
Помогите раскодировать строки
я начинающий программист и я пишу на языке golang. Сейчас у меня не большой проект где нужно реализовать сервис который слушает почту и принимает письма из ящика. Для реализации всего этого я .
Можно ли редактировать текст с помощью Regex без цикла?
Например выполнить задачу с помощью Regex: Текст на ввод: it (cap) was the best of TIMES (low) Текст на вывод: It was the best of times (cap) это у нас в роле Сapitalize,и суть задачи применить .
передача данных между middlewares
всем привет. у меня есть несколько мидлваре в проекте, они запускаются одна за другой при запросе определенного урла перед тем как запустить финальный хэндлфанк Я столкнулся с тем что данные из .
Что означает запись в go?
Искал примеры реализации десктоп-приложений в go, наткнулся на запись вида func (ap *AppGUI) Run() < >AppGUI - Структура (struct). Что это за обращение? Каким образом можно обратится к этой функции, .
Традиционно первая программа, с которой начинается изучение любого языка программирования, называется «Hello World» — эта программа просто выводит в консоль строку Hello World . Давайте напишем её с помощью Go.
Сначала создадим новую директорию, в которой будем хранить нашу программу. Установщик, о котором говорилось в первой главе, создал в вашей домашней директории каталог Go . Теперь создайте директорию под названием ~/Go/src/golang-book/chapter2 (где ~ означает вашу домашнюю директорию). Вы можете сделать это из терминала с помощью следующих команд:
Используя текстовый редактор, введите следующее:
Убедитесь, что содержимое файла идентично показанному здесь примеру, и сохраните его под именем main.go в созданной ранее директории. Затем откройте новое окно терминала и введите:
Как читать программу на Go
Теперь давайте рассмотрим программу более детально. Программы на Go читаются сверху вниз, слева направо (как книга). Первая строка гласит:
Это называется «определением пакета». Любая Go программа должна начинаться с определения имени пакета. Пакеты — это подход Go к организации и повторному использованию кода. Есть два типа программ на Go: исполняемые файлы и разделяемые библиотеки. Исполняемые файлы являются видом программ, которые можно запустить прямо из терминала (в Windows их имя заканчивается на .exe ). Библиотеки являются коллекциями кода, который можно использовать из других программ. Детальнее мы будем рассматривать библиотеки чуть позже, а пока просто не забудьте включать эту строку в программы, которые вы пишете.
Далее следует пустая строка. Компьютер представляет новые строки специальным символом (или несколькими символами). Символы новой строки, пробелы и символы табуляции называются разделителями. Go не обращает на них внимания, но мы используем их, чтобы облегчить себе чтение программы (вы можете удалить эту строку и убедиться, что программа ведет себя в точности как раньше).
Дальше следует это:
Ключевое слово import позволяет подключить сторонние пакеты для использования их функциональности в нашей программе. Пакет fmt (сокращение от format) реализует форматирование для входных и выходных данных. Учитывая то, что мы только что узнали о пакетах, как вы думаете, что будет содержаться в верхней части файлов пакета fmt ?
Обратите внимание, что fmt взят в двойные кавычки. Использование двойных кавычек называется «строковым литералом», который в свою очередь является видом «выражения». Строки в Go представляют собой набор символов (букв, чисел, …) определенной длины. Строки мы рассмотрим детально в следующей главе, а сейчас главное иметь в виду, что за открывающим символом " в конечном итоге должен последовать и закрывающий. Всё, что находится между ними, будет являться строкой (символ " сам по себе не является частью строки).
Строка, начинающаяся с // , является комментарием. Комментарии игнорируются компилятором Go и служат пояснениями исключительно для вас (или для тех, кто будет потом читать ваш код). Go поддерживает два вида комментариев: // превращает в комментарий весь текст до конца строки и /* */ , где комментарием является всё, что содержится между символами * (включая переносы строк).
Далее можно увидеть объявление функции:
Функции являются кирпичиками программы на Go. Они имеют входы, выходы и ряд действий, называемых операторами, расположенных в определенном порядке. Любая функция начинается с ключевого слова func за которым следуют: имя функции (в нашем случае main ), список из нуля и более параметров в круглых скобках, возвращаемый тип (если есть) и само «тело», заключенное в фигурные скобки. Наша функция не имеет входных параметров, ничего не возвращает и содержит всего один оператор. Имя main является особенным, эта функция будет вызываться сама при запуске программы.
Заключительной частью нашей программы является эта строка:
Этот оператор содержит три части: доступ к функции пакета fmt под названием Println (Print line), затем создание новой строки, содержащей Hello World , и вызов функции с этой строкой в качестве первого и единственного аргумента.
На данный момент вы уже можете быть немного перегружены количеством новых терминов. Иногда полезно не спеша прочесть вашу программу вслух. Программу, которую мы только что написали, можно прочитать следующим образом:
Создать новую исполняемую программу, которая использует библиотеку fmt и содержит функцию main . Эта функция не имеет аргументов, ничего не возвращает и делает следующее: использует функцию Println из библиотеки fmt и вызывает её, передавая один аргумент — строку Hello World .
Функция Println выполняет основную работу в этой программе. Вы можете узнать о ней больше, набрав в терминале команду:
Среди прочей информации вы должны увидеть это:
Сейчас документация говорит нам, что вызов Println пошлет передаваемые ей данные на стандартный вывод — терминал, вы сейчас работаете в нём. Эта функция является причиной, по которой Hello World отображается на экране.
В следующей главе вы поймете, каким образом Go хранит и представляет вещи вроде Hello World с помощью типов.
Задачи
Что такое разделитель?
Что такое комментарий? Назовите два способа записи комментариев.
Наша программа начиналась с package main . С чего начинаются файлы в пакете fmt ?
Мы использовали функцию Println из пакета fmt . Если бы мы хотели использовать функцию Exit из пакета os , что бы для этого потребовалось сделать?
Измените написанную программу так, чтобы вместо Hello World она выводила Hello, my name is вместе с вашем именем.
Go разработан как язык, который поощряет хорошие инженерные практики. Одной из этих практик, позволяющих создавать высококачественное программное обеспечение, является повторное использование кода, называемое DRY — «Don't Repeat Yourself» — (акроним, в переводе с английского) — «не повторяйтесь!». Как мы уже видели в 7 главе, функции являются первым уровнем повторного использование кода. Но Go поддерживает ещё один механизм для повторного использования кода — пакеты. Почти любая программа, которую мы видели, включает эту строку:
fmt — это имя пакета, включающего множество функций, связанных с форматированием строк и выводом на экран. Данный метод распространения кода обусловлен тремя причинами:
Снижение вероятности дублирование имён функций, что позволяет именам быть простыми и краткими
Организация кода для упрощения поиска повторно используемых конструкций
Ускорение компиляции, так как мы должны перекомпилировать только части программы. Несмотря на то, что мы используем пакет fmt , мы не должны перекомпилировать его при каждом использовании
Создание пакета
Использовать пакеты имеет смысл, только когда они востребованы отдельной программой. Без неё использовать пакеты невозможно.
Давайте создадим программу, которая будет использовать наш пакет. Создадим директорию в ~/Go/src/golang-book под названием chapter11 . В ней создадим файл main.go с этим кодом:
А теперь создадим ещё одну директорию внутри chapter11 под названием math В ней мы создадим файл math.go с этим кодом:
C помощью терминала в папке math запустите команду go install . В результате файл math.go скомпилируется в объектный файл ~/Go/pkg/os_arch/golang-book/chapter11/math.a (при этом, os может быть Windows , a arch , например, — amd64)
Теперь вернёмся в директорию chapter11 и выполним go run main.go . Программа выведет 2.5 на экран. Подведём итоги:
math является встроенным пакетом, но так как пакеты Go используют иерархические наименование, мы можем перекрыть уже используемое наименование, в данном случае настоящий пакет math и будет называться math , а наш — golang-book/chapter11/math .
Когда мы импортируем библиотеку, мы используем её полное наименование import "golang-book/chapter11/math" , но внутри файла math.go мы используем только последнюю часть названия — package math .
Мы используем только краткое имя math когда мы обращаемся к функциям в нашем пакете. Если же мы хотим использовать оба пакета, то мы можем использовать псевдоним:
В этом коде m — псевдоним.
Возможно вы заметили, что каждая функция в пакете начинается с заглавной буквы. Любая сущность языка Go, которая начинается с заглавной буквы, означает, что другие пакеты и программы могут использовать эту сущность. Если бы мы назвали нашу функцию average , а не Average , то наша главная программа не смогла бы обратиться к ней.
Рекомендуется делать явными только те сущности нашего пакета, которые могут быть использованы другими пакетами, и прятать все остальные служебные функции, не используемые в других пакетах. Данный подход позволяет производить изменения в скрытых частях пакета без риска нарушить работу других программ, и это облегчает использование нашего пакета
Имена пакетов совпадают с директориями, в которых они размещены. Данное правило можно обойти, но делать это нежелательно.
Документация к коду
Go позволяет автоматически создавать документацию к пользовательским пакетам так же, как и документировать стандартные пакеты. Запустите эту команду в терминале:
И вы увидите информацию о функции, которую мы только что написали. Мы можем улучшить документацию, добавив комментарий перед функцией:
Если вы запустите go install , а потом перезапустите:
то вы увидите наш комментарий — Найти среднее в массиве чисел . Также вы можете увидеть документацию на интернет-странице, запустив в терминале команду:
Вы увидите документацию по всем пакетам, установленным в системе, в том числе и про наш пакет.
Задачи
Зачем мы используем пакеты?
Чем отличаются программные сущности, названные с большой буквы? То есть, чем Average отличается от average ?
Что такое псевдоним пакета и как его сделать?
Мы скопировали функцию Average из главы 7 в наш новый пакет. Создайте Min и Max функции для нахождения наименьших и наибольших значений в срезах дробных чисел типа float64 .
Читайте также: