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

В этом посте мы рассмотрим, как создать «проект» Go, который позволяет нам распределять функции по нескольким файлам.

Давайте начнем с краткого обзора того, как мы обычно это делаем в .NET. Предполагая, что вы используете Visual Studio, типичный путь для создания консольного приложения находится в меню файла:

File -> New Project -> Console Application

Visual Studio создает для нас файл решения, файл проекта и файл программы, который содержит функцию входа для нашего приложения.

Файлы решения и проекта - это «файлы метаданных». Файлы, содержащие всю информацию, необходимую компилятору для создания нашей программы, входные файлы, выходные файлы, целевую платформу, кодировку и так далее. Все. Итак, когда мы нажимаем F5, IDE знает, как создать и запустить нашу программу.

(Visual Studio также создает файлы конфигурации, информацию о сборке, ресурсы и т. д. Я пропустил их, потому что они не имеют отношения к теме этого сообщения).

Когда мы добавляем еще один файл в наш проект, Visual Studio обновляет файл проекта, поэтому компилятор знает, как его найти во время сборки. Для нас этот процесс прозрачен. Нам не нужно делать ничего другого, чтобы запустить программу, содержащую один файл, или, если уж на то пошло, тысяча - это примерно одно и то же. Мы просто нажимаем F5, и все работает.

В Go все немного иначе. Во-первых, нет файлов проекта (по крайней мере, в базовых настройках). Большинство вещей осуществляется по соглашениям, что приятно, если вы к ним привыкнете, но немного сложно, если вы привыкли к IDE, где все просто работает.

Как мы уже говорили в предыдущем посте, файлы go живут внутри пакетов, поэтому давайте создадим пакет для нашего консольного приложения.

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

Начнем с создания папки пакета и файла программы.

$ cd $GOPATH/src
$ mkdir console
$ cd console
$ touch program.go

Теперь мы добавляем код в наш программный файл:

package main
import (
    "fmt"
)
func main() {
    fmt.Printf("Hello World!\n")
}

Наконец, мы запускаем нашу программу с помощью команды go run, чтобы проверить, все ли работает должным образом:

$ go run program.go
Hello World!

Потрясающий!

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

package main
import (
    "fmt"
)
func main() {
    fmt.Printf(strcat("Hello ", "World!\n"))
}
func strcat(s1, s2 string) string {
    return fmt.Sprintf("%s%s", s1, s2)
}

Давайте запустим нашу программу еще раз, чтобы проверить, работает ли функция strcat.

$ go run program.go
Hello World!

Все идет нормально. Но мы все еще работаем над одним файлом. Пришло время создать новый файл и больше функций.

Назовем этот файл utils.go.

$ touch utils.go
package main
import (
    "fmt"
)
func strcat(s1, s2 string) string {
    return fmt.Sprintf("%s%s", s1, s2)
}

Обратите внимание, что мы должны указать, что файл принадлежит пакету main. Это обязательно. Недостаточно поместить файл в папку пакета. Мы должны сообщить компилятору, что файл принадлежит пакету.

Хорошо, теперь пора запустить нашу программу и посмотреть, сможет ли компилятор Go определить местонахождение функции «strcat».

$ go run program.go
# command-line-arguments
./program.go:8:13: undefined: strcat

Неа. Это умно, но не настолько;)

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

Давайте попробуем еще раз, но на этот раз с использованием подстановочного знака, чтобы включить все файлы Go из текущего каталога.

$ go run *.go
Hello World!

Конечно, теперь он печатает «Hello World!».

Обратите внимание, что нам не нужно было включать / reference utils.go. Пока файл принадлежит тому же пакету, в котором используются его функции, компилятор достаточно умен, чтобы работать и включать их за нас.

Это для этого поста, в следующий раз мы рассмотрим операторы потока управления. Быть в курсе!

PS: Не забывайте хлопать, если вам понравился этот пост!