Наша программа началась с package main с чего начнутся файлы в fmt package

Обновлено: 07.07.2024

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

Код пакета располагается в одном или нескольких файлах с расширением go . Для определения пакета применяется ключевое слово package . Например:

В данном случае пакет называется main . Определение пакета должно идти в начале файла.

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

Импорт пакетов

Нередко программы подключают сразу несколько внешних пакетов. В этом случае можно последовательно импортировать каждый пакет:

В данном случае подключается встроенный пакет math, который содержит функцию Sqrt() , возвращающую квадратный корень числа.

Либо чтобы сократить определение импорта пакетов можно заключить все пакеты в скобки:

Пакет из нескольких файлов

Один пакет может состоять из нескольких файлов. Например, определим в папке два файла:

Multiple files in Go build

В файле factorial.go определим функцию для подсчета факториала:

Данный файл принадлежит пакету main.

В файле main.go используем функцию для вычисления факториала:

Данный файл также принадлежит пакету main. Файлов может и быть и больше. Теперь скомпилируем из этих файлов программу. Для этого перейдем в консоли к папке проекта и выполним команду:

Флаг -o указывает, как будет называться выходной файл - в данном случае main.exe. Затем идут все компилируемые файлы. После выполнения этой команды будет создан файл main.exe, который мы сможем запустить в консоли:

Компиляция файлов Go

Файлы в разных пакетах

Теперь рассмотрим другую ситуацию, когда файлы нашей программы разделены по разным пакетам. Определим в папке проекта каталог computation . Затем в каталог computation добавим следующий файл factorial.go:

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

Импорт пакетов в Go

И чтобы использовать функцию factorial, надо импортировать этот пакет в файле main.go:

Путь "./computation" указывает, что пакет находится в папке computation.

Компиляция и выполнение программы осуществляется также как и ранее без необходимости указания всех файлов из других пакетов:

Традиционно первая программа, с которой начинается изучение любого языка программирования, называется «Hello World» — эта программа просто выводит в консоль строку Hello World . Давайте напишем её с помощью Go.

программу на Go

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

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

Используя текстовый редактор, введите следующее:

Убедитесь, что содержимое файла идентично показанному здесь примеру, и сохраните его под именем main.go в созданной ранее директории. Затем откройте новое окно терминала и введите:

Видео на тему: Введение в язык программирования 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 изучать notes-day11 (изучение Go с точки зрения Java)

Читать и записывать данные

Примечание: окончания строк в Unix и Windows различны! Так же, как в Java

  • Чтение и запись файлов
  • Читать файл
    В Go файлы представлены указателями на типы os.File, также называемые дескрипторами файлов. Мы использовали стандартный ввод os.Stdin и стандартный вывод os.Stdout в предыдущей главе, и оба они имеют тип * os.File.

Переменная inputFile имеет тип * os.File. Этот тип представляет собой структуру, которая представляет дескриптор открытого файла (дескриптор файла). Затем используйте функцию Open в пакете os, чтобы открыть файл. Параметр этой функции - имя файла, а тип - строка. В приведенной выше программе мы открываем файл input.dat в режиме только для чтения.
Если файл не существует или программа не имеет достаточных разрешений для открытия файла, функция Open выдаст ошибку: inputFile, inputError = os.Open ("input.dat"). Если файл открывается нормально, мы используем оператор defer inputFile.Close (), чтобы убедиться, что файл закрыт до выхода из программы. Затем мы используем bufio.NewReader для получения переменной читателя.
Используя читатель, предоставляемый пакетом bufio (писатель также похож), как показано в приведенной выше программе, мы можем легко управлять строковыми объектами относительно высокого уровня без необходимости работать Сравните основные байты.
Далее, мы используем ReadString ('\ n') или ReadBytes ('\ n') в бесконечном цикле для чтения содержимого файла строка за строкой (символ конца строки '\ n') Возьми это.
Примечание. В предыдущем примере мы видели, что окончания строк для Unix и Linux - это \ n, а окончания строк для Windows - \ r \ n. При использовании методов ReadString и ReadBytes нам не нужно заботиться о типе операционной системы, просто используйте \ n. Кроме того, мы также можем использовать метод ReadLine () для достижения той же функции.
Как только конец файла будет прочитан, значение переменной readerError станет ненулевым (на самом деле его значение является константой io.EOF), и мы выполним инструкцию return для выхода из цикла.

  1. Прочитайте содержимое всего файла в строку:
    Вы можете использовать метод ioutil.ReadFile () в пакете io / ioutil. Первое возвращаемое значение этого метода - байт [], в котором хранится прочитанное содержимое, второе Возвращаемое значение является ошибкой. Если ошибка не возникает, второе возвращаемое значение равно нулю. Аналогично, функция WriteFile () может записать значение байта [] в файл.


Буферизованное чтение
Во многих случаях содержимое файла не делится на строки или просто двоичный файл. В этом случае ReadString () не может быть использован. Мы можем использовать bufio.Reader's Read (), который получает только один параметр:
Значение переменной n указывает количество прочитанных байтов.

Обратите внимание на использование defer: если при открытии целевого файла возникает ошибка, тогда defer может обеспечить выполнение src.Close (). Если вы этого не сделаете, файл останется открытым и займет ресурсы.

Мы запускаем эту программу прямо в IDE или в редакторе: Доброе утро, Алиса
Если мы запустим os_args или ./os_args в командной строке, мы получим тот же результат.
Но мы добавим параметры в командной строке, например: os_args Джон Билл Марк Люк, получит следующий вывод: Доброе утро, Алиса Джон Билл Марк Люк
Этот параметр командной строки будет помещен в фрагмент os.Args [] (разделенный пробелами), начиная с индекса 1 (os.Args [0] задает имя самой программы, в В этом случае os_args). Функция strings.Join соединяет эти параметры в пробелах.

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

flag.Parse () сканирует список параметров (или список констант) и устанавливает флаг, flag.Arg (i) представляет i-й параметр. После того, как Parse () flag.Arg (i) все доступно, flag.Arg (0) является первым реальным флагом, а не именем программы, как os.Args (0).
flag.Narg () возвращает количество параметров. После разбора флаг или константа становятся доступными. flag.Bool () определяет флаг со значением по умолчанию false: когда первый параметр появляется в командной строке (здесь «n»), для флага устанавливается значение true (NewLine имеет тип * bool). Флаг разыменовывается до * NewLine, поэтому, когда значение равно true, будет добавлена ​​новая строка ("\ n").
flag.PrintDefaults () выводит справочную информацию для flag, в этом примере она печатает:
-n=false: print newline
flag.VisitAll (fn func (* Flag)) - это еще одна полезная функция: обход флага в лексикографическом порядке и вызов fn для каждой метки
При выполнении в командной строке (Windows): echo.exe A B C выдает: A B C; выполняет echo.exe -n A B C, выдает:
A
B
C
Каждый выводимый символ имеет новую строку, и справочная информация каждый раз печатается перед выходными данными: -n = false: вывод новой строки.
Для flag.Bool вы можете установить логический флаг для проверки вашего кода, например, определить флаг processingFlag:
var processedFlag = flag.Bool(“proc”, false, “nothing processed yet”)
Затем используйте следующий код для проверки:
if *processedFlag < // found flag -proc
r = process()
>
Чтобы определить другие типы флагов, вы можете использовать flag.Int (), flag.Float64 (), flag.String ().

  • Используйте буфер для чтения файлов
    использует комбинацию файла чтения буфера и разбора флага командной строки. Если никакие параметры не добавляются, то печатается любой экран, который вы вводите.
    Параметр считается именем файла, и если файл существует, содержимое файла выводится на экран. Запустите cat test в командной строке, чтобы проверить вывод.
  • Чтение и запись файлов с кусочками
    Слайсинг обеспечивает стандартный способ обработки буферов ввода-вывода в Go. Во второй версии функции cat, приведенной ниже, бесконечный цикл for (до EOF в конце файла) используется для чтения в буфере слайсов Файл и запись в стандартный вывод (os.Stdout).

Выполняется f.Close () после возврата функции

  • Практический пример использования интерфейса: fmt.Fprintf

Хотя XML широко используется, JSON более лаконичен, легок (занимает меньше памяти, дисков и пропускной способности сети) и лучше читается, что делает его все более популярным.
Пакет json на языке Go позволяет легко читать и записывать данные JSON в программе.
Мы будем использовать пакет json в следующем примере и использовать упрощенную версию структур Address и VCard из упражнения 10.1 vcard.go

Десериализация:
Сигнатура функции UnMarshal () - это func Unmarshal (data [] byte, v interface <>) Ошибка. Декодируйте JSON в структуру данных.
Декодировать данные в структуру
Если мы заранее знаем данные JSON, мы можем определить подходящую структуру и десериализовать данные JSON. В следующем примере мы определим:

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


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

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

  • Настройте программное окружение Go (о том, как это сделать, можно узнать здесь). Создайте рабочее пространство Go (этому посвящён пятый пункт вышеупомянутого материала). В следующем разделе этого материала вы сможете найти примеры, которые рекомендуется воспроизвести у себя. Так вы сможете лучше с ними разобраться.
  • Для того чтобы углубить свои знания по GOPATH — взгляните на этот материал.

Написание и импорт пакетов

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

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


Мы собираемся назвать пакет, который будем разрабатывать в этом руководстве, greet . Для того чтобы это сделать — создадим директорию greet в директории gopherguides . В результате имеющаяся структура папок приобретёт следующий вид:


Теперь мы готовы к тому, чтобы добавить в директорию greet первый файл. Обычно файл, который является входной точкой (entry point) пакета, называют так же, как названа директория пакета. В данном случае это означает, что мы, в директории greet , создаём файл greet.go :


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

Откройте файл greet.go в текстовом редакторе и добавьте в него следующий код:


Разберём содержимое этого файла. Первая строка каждого файла должна содержать имя пакета, в котором мы работаем. Так как мы находимся в пакете greet — здесь используется ключевое слово package , за которым следует имя пакета:


Это сообщает компилятору о том, что он должен воспринимать всё, что находится в файле, как часть пакета greet .

Далее выполняется импорт необходимых пакетов с помощью выражения import . В данном случае нам нужен всего один пакет — fmt :


И, наконец, мы создаём функцию Hello . Она будет использовать возможности пакета fmt для вывода на экран строки Hello, World! :


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

А именно, мы создадим пакет example . Для этого будем исходить из тех же предположений, из которых исходили, создавая пакет greet . Для начала создадим папку example в папке gopherguides :


Теперь создаём файл, являющийся входной точкой пакета. Данный пакет мы рассматриваем как выполняемую программу, а не как пакет, код которого планируется использовать в других пакетах. Файлы, являющиеся входными точками программ, принято называть main.go :


Откройте в редакторе файл main.go и внесите в него следующий код, который позволяет воспользоваться возможностями пакета greet :


Мы импортировали в файле main.go пакет greet , а это значит, что для вызова функции, объявленной в этом пакете, нам понадобится воспользоваться точечной нотацией. Точечная нотация — это конструкция, в которой между именем пакета и именем ресурса этого пакета, который нужно использовать, ставится точка. Например, в пакете greet роль ресурса играет функция Hello . Если нужно вызвать эту функцию — используется точечная нотация : greet.Hello() .

Теперь можно открыть терминал и запустить программу:


После того, как вы это сделаете, в терминале будет выведено следующее:


Теперь поговорим о том, как использовать переменные, объявляемые в пакетах. Для этого добавим объявление переменной в файл greet.go :


Откройте файл main.go и добавьте в него строку, в которой функция fmt.Println() используется для вывода значения переменной Shark , объявленной в пакете greet.go . А именно, приведите main.go к следующему виду:


Снова запустите программу:


Теперь она выведет следующее:


А сейчас поговорим о том, как объявлять в пакетах типы. Создадим тип Octopus с полями Name и Color , а также создадим метод типа. Этот метод, при его вызове, будет возвращать особым образом обработанное содержимое полей типа Octopus . Приведём greet.go к следующему виду:


Теперь откройте main.go , создайте в нём экземпляр структуры нового типа и обратитесь к его методу String() :


После того, как вы, с помощью конструкции, которая выглядит как oct := greet.Octopus , создали экземпляр Octopus , вы можете обращаться к методам и свойствам типа из пространства имён файла main.go . Это, в частности, позволяет воспользоваться командой oct.String() , расположенной в конце файла main.go , не обращаясь к greet . Кроме того, мы можем, например, обратиться к полю структуры Color , воспользовавшись конструкцией oct.Color . При этом мы, как и тогда, когда вызывали метод, не обращаемся к greet .

Метод String типа Octopus использует функцию fmt.Sprintf для формирования предложения и возвращает, с помощью return , результат, строку, в место вызова метода (в данном случае это место находится в main.go ).

Запустим программу снова:


Она выведет в консоль следующее:


Теперь, когда мы оснастили Octopus методом String , мы получили механизм вывода сведений о типе, подходящий для многократного использования. Если в будущем понадобится изменить поведение этого метода, который может использоваться во многих проектах, достаточно будет один раз отредактировать его код в greet.go .

Экспорт сущностей

Возможно, вы обратили внимание на то, что всё, с чем мы работали, обращаясь к пакету greet , имеет имена, начинающиеся с прописной буквы. В Go нет модификаторов доступа наподобие public , private или protected , которые есть в других языках. Видимость сущностей для внешних механизмов контролируется тем, с какой буквы, с маленькой или с большой, начинаются их имена. В результате типы, переменные, функции, имена которых начинаются с прописной буквы, доступны за пределами текущего пакета. Код, который виден за пределами пакета, называется экспортированным.

Если оснастить тип Octopus новым методом с именем reset , то этот метод можно будет вызывать из пакета greet , но не из файла main.go , который находится за пределами пакета greet . Вот обновлённый вариант greet.go :


Попытаемся вызвать reset из файла main.go :


Это приведёт к появлению следующей ошибки компиляции:


Для того чтобы экспортировать метод reset типа Octopus нужно его переименовать, заменив первую букву, строчную r , на прописную R . Сделаем это, отредактировав greet.go :


Вот что попадёт в консоль:


Вызвав метод Reset , мы очистили поля Name и Color нашего экземпляра Octopus . В результате, при вызове String , там, где раньше выводилось содержимое полей Name и Color , теперь не выводится ничего.

Итоги

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

Читайте также: