Как импортировать функцию из другого файла golang

Обновлено: 04.07.2024

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

В этом контексте под видимостью подразумевается файловое пространство, откуда можно ссылаться на пакет или другой конструкционный элемент. Например, если мы определим переменную в функции, видимость (сфера действия) этой переменной будет только внутри функции, где она определена. Если же мы определим переменную в пакете, ее можно будет сделать видимой только для этого пакета или разрешить доступ к ней из-за пределов пакета.

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

Для выполнения примеров из этой статьи вам потребуется следующее:

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

Экспортированные и неэкспортированные элементы

В отличие от таких языков программирования, как Java и Python, где используются различные* модификаторы доступа*, декларирующие элементы как public , private или protected . Декларирование помогает Go определить, являются ли элементы экспортированными или неэкспортированными . В этом случае экспорт элемента делает его видимым за пределами текущего пакета. Если элемент не экспортирован, его можно видеть и использовать только внутри пакета, где он определен.

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

Рассмотрим следующий код, обращая особое внимание на использование заглавных букв:

Этот код декларирует, что он содержится в пакете greet . Затем он декларирует два символа: переменную Greeting и функцию Hello . Поскольку они начинаются с заглавной буквы, они являются экспортируемыми и доступны любой внешней программе. Как уже говорилось выше, создание пакета с ограничением доступа позволит лучше проектировать API и упростит внутреннее обновление пакета без нарушения работы кода, зависящего от вашего пакета.

Определение видимости пакета

Создайте в каталоге src каталог с именем logging , где будут размещены наши файлы регистрации:

Перейдите в этот каталог:

Используйте nano или другой редактор для создания файла logging.go :

Поместите следующий код в созданный нами файл logging.go :

В первой строчке этого кода декларируется пакет с именем logging . В этом пакете содержится две экспортируемые функции: Debug и Log . Эти функции сможет вызывать любой другой пакет, импортирующий пакет logging . Также существует private переменная с именем debug . Эта переменная доступна только из пакета logging . Важно отметить, что функция Debug и переменная debug имеют одинаковое написание, но имя функции начинается с заглавной буквы, а имя переменной — нет. Это обеспечивает отдельное декларирование с разной сферой действия.

Сохраните и закройте файл.

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

Выйдем из каталога logging , создадим новый каталог cmd и перейдем в этот новый каталог:

Создайте файл с именем main.go в каталоге cmd , который мы только что создали:

Теперь мы можем добавить следующий код:

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

Откройте следующий файл go.mod в каталоге cmd :

Затем поместите в файл следующий код:

Также нам потребуется файл go.mod для нашего пакета logging . Вернемся в каталог logging и создадим файл go.mod :

Добавьте в файл следующие строчки:

Теперь у вас должны быть следующая структура каталогов и расположение файлов:

Мы завершили настройку и теперь можем запустить программу main из пакета cmd с помощью следующих команд:

Результат должен выглядеть примерно следующим образом:

Программа выведет текущее время в формате RFC 3339, а затем выражение, которое мы отправили в регистратор. RFC 3339 — это формат времени, разработанный для представления времени в интернете и обычно используемый в файлах журналов.

Поскольку функции Debug и Log экспортированы из пакета logging, мы можем использовать их в нашем пакете main . Однако переменная debug в пакете logging не экспортируется. Попытка ссылки на неэкспортированную декларацию приведет к ошибке во время компиляции.

Добавьте следующую выделенную строку в файл main.go :

Мы увидели поведение экспортированных и неэкспортированных элементов в пакетах, а теперь посмотрим, как можно экспортировать поля и методы из структур .

Видимость в структурах

Хотя построенная нами в предыдущем разделе схема видимости может работать для простых программ, она передает слишком много значений состояния, чтобы быть полезной в нескольких пакетах. Это связано с тем, что экспортированные переменные доступны многим пакетам, которые могут изменять переменные до конфликтующих состояний. Если разрешить подобное изменение состояния пакета, будет сложно прогнозировать поведение программы. Например, при текущей схеме один пакет может задать для переменной Debug значение true , а другой — значение false для того же самого экземпляра. Это создаст проблему, поскольку будет влиять на оба пакета, импортирующих пакет logging .

Мы можем изолировать регистратор, создав структуру и передав ей методы. Это позволит нам создавать экземпляр регистратора, который будет использоваться независимо в каждом пакете.

В этом коде мы создали структуру Logger . В этой структуре будет размещено неэкспортированное состояние, включая формат времени для вывода и значение переменной debug — true или false . Функция New задает начальное состояние для создания регистратора, в частности формат времени и статус отладки. Она сохранит присвоенные внутренние значения в неэкспортированные переменные timeFormat и debug . Также мы создали метод Log типа Logger , который принимает выражение, которое мы хотим вывести. В методе Log содержится ссылка на переменную локального метода l для получения доступа к таким его внутренним полям, как l.timeFormat и l.debug .

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

Чтобы использовать его в другом пакете, изменим cmd/main.go следующим образом:

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

В этом коде мы создали экземпляр регистратора, вызвав экспортированную функцию New . Мы сохранили ссылку на этот экземпляр в переменной logger . Теперь мы можем вызывать logging.Log для вывода выражений.

Если мы попытаемся сослаться на неэкспортированное поле из Logger , например, на поле timeFormat , при компиляции будет выведена ошибка. Попробуйте добавить следующую выделенную строку и запустить cmd/main.go :

Компилятор определяет, что logger.timeFormat не экспортируется, и поэтому не может быть получен из пакета logging .

Видимость в методах

Методы, как и поля структуры, могут быть экспортируемыми или неэкспортируемыми.

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

Уровень info , представляющий события информационного типа, сообщающие пользователю о действии, например, Program started или Email sent . Они помогают выполнять отладку и отслеживать части программы, чтобы определять ожидаемое поведение.

Уровень warning . Эти события определяют непредвиденные события, которые не представляют собой ошибку, например, Email failed to send, retrying . Они помогают понять, какие части программы работают не так хорошо, как мы ожидали.

Уровень error , означающий, что в программе возникла проблема, например, File not found . Часто это вызывает прекращение работы программы.

Для добавления многоуровневой регистрации нужно внести следующие изменения в файл logging/logging.go :

Теперь мы можем использовать многоуровневую регистрацию в другом пакете, изменив cmd/main.go следующим образом:

При запуске вы увидите следующее:

В этом примере cmd/main.go успешно использует экспортированный метод Log .

Если мы попытаемся вызвать метод write из-за пределов пакета logging , мы получим ошибку компиляции:

Заключение

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

Дополнительную информацию о пакетах в Go можно найти в статьях Импорт пакетов в Go и Написание пакетов в Go, а также в других статьях серии по программированию на Go.

Я хочу вызвать функцию из другого файла на go lang, может ли кто-нибудь помочь?

Как звонить demo в test2 с test1 ?

Что вы имеете в виду go fmt ? Вроде в терминале что ли? Как это показать, что он обо всем заботится?

В main вашем пакете не может быть больше одного .

В более общем смысле, у вас не может быть более одной функции с данным именем в пакете.

Удалите main in test2.go и скомпилируйте приложение. demo Функция будет видна с test1.go .

Я могу собрать и запустить после удаления main в test2.go, но не смог запустить test1.go с помощью go run test1.go still. Зачем ? @RichChurcher, ты дал ответ. Спасибо . Также вы должны использовать Demo () в верхнем регистре , публичные функции по соглашению имеют верхний регистр Если у test2 есть структура, будет ли она импортирована?

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

Выполните любую из следующих двух команд:

Вы должны сделать то же самое, если хотите их построить.

Я искал то же самое. Чтобы ответить на ваш вопрос « Как вызвать demo в test2 из test1? », Вот как я это сделал. Запустите этот код с помощью go run test1.go команды. Измените current_folder на папку, в которой находится test1.go.

test1.go

lib \ test2.go

Поместите файл test2.go в подпапку lib

Убедитесь, что имя метода написано с большой буквы, иначе он не сработает. Извините, но это явно не работает: package lib; expected main

Если вы просто запустите, go run test1.go и этот файл содержит ссылку на функцию в другом файле в том же пакете, это приведет к ошибке, потому что вы не сказали Go запустить весь пакет, вы сказали ему запустить только этот один файл.

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

go run test1.go test2.go

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

go build test1.go test2.go

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

Или как бы то ни было, когда имя вашего исполняемого файла было вызвано при его создании.

Добрый вечер. Никак не могу разобраться с тем6 как подключать файлы в проекте со структурой. Допустим имеется такой проект:

Как подключить файл conf.go в main.go? Указанный вариант не работает. __________________
Помощь в написании контрольных, курсовых и дипломных работ здесь

[MFC] Подключение внешних зависимостей и заголовочных файлов другого проекта
Здравствуйте. Хотелось бы узнать, есть ли такая возможность? Хочу, чтобы моему проекту были.


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

Проблемы с подключением .h файлов сторонних библиотек из .h файлов проекта
Здравствуйте, господа и дамы. Пишу .lib библиотеку с использованием SDL. Есть класс, имеющий.

О, да .. тоже потрахался на прошлой неделе ..

Ваш проект должен расти из папки src .. если нет модулей.

В вашем случае должно быть что-то такое

но советую использовать go modules

и тогда main.go будет выглядеть следующим образом

Ваш проект должен расти из папки src .. если нет модулей.

Структура проекта - это отдельная очень грустная тема в Go. Папки, на самом деле, могут называться как угодно. Все эти pkg, src, cmd - условности.


В общем, еще немного порылся в сети (это было не просто) и нашел вот такую статью: How to Import struct from another or child package? Там как раз дается пример с использованием go mod init.

Вроде сделал все по аналогии (VSC даже автоматически подставил мне myapp/conf в раздел import). Но при запуске main.go получаю такую ошибку:

А вот при переводе проекта в модули командой go mod init все НАОБОРОТ, проект НЕ должен расти из папки src .. как раз сегодня с этим трахался..

И таки да, относительные пути импорта разработчики Go настоятельно не рекомендуют. Короче Низзя так.

А вот при переводе проекта в модули командой go mod init все НАОБОРОТ, проект НЕ должен расти из папки src .. как раз сегодня с этим трахался..

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

И таки да, относительные пути импорта разработчики Go настоятельно не рекомендуют. Короче Низзя так. Данная проблема до сих пор наблюдается? Попробуйте настроить GOPATH, не перепутайте с GOROOT. Оно заработало! Я не знаю как, но заработало. Go такой Go. У меня все работало с первой команды go mod init. Не понимаю людей, у которых это не работает.
Все ж написано: хотите модули - создайте модуль за пределами GOPATH и будьте счастливы.
Начиная с Go 1.11, команда go позволяет использовать модули, когда текущий или любой родительский каталог имеет go.mod, при условии, что каталог находится за пределами $GOPATH/src. (Внутри $GOPATH/src для совместимости команда go по-прежнему выполняется в старом режиме GOPATH, даже если найден go.mod. Начиная с версии Go 1.13, режим модуля будет использоваться по умолчанию для всей разработки.

Запрос на объединение одинаковых по структуре файлов из определенной папки
Всем привет! Подскажите, пожалуйста, как создать запрос на объединение одинаковых по структуре.


Нужно скачать большое количество файлов которые лежат в определенной структуре каталогов
Нужно скачать большое количество файлов которые лежат в определенной структуре каталогов. Мне нужно.

Подключение проекта
Есть проект написанный на бд, а также sql база , пытаюсь соединить не получается, точнее не могу.

Подключение проекта к проекту
Объясните, пожалуйста, как в visual studio создать 2 проекта в одном, как на скриншоте

Подключение проекта к проекту
Добрый вечер, прощу подсказки почему у меня "отваливается" проект прикрепленный к проекту Что.

Подключение к БД из Silverlight-проекта
Нажимаю add data source в проекте silverlight, а там нет в списке database, только service, object.

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

Если бы я поместил PriorityQueue вместе со всеми его методами в один и тот же файл, я бы объявил его с помощью

Я как сумасшедший искал в интернете ответ на этот простой вопрос, но так и не нашел ответа. Я обычно программирую в java и импортирую классы так элементарно.

2 ответа

Я использую этот код для импорта файла shutdownscheduler.xml из моего пакета, но получаю ошибку: public static Document handler() throws ParserConfigurationException, SAXException, IOException< String s=xmlhandler.class.getResource(shutdownscheduler.xml).toString(); File newFile=new File(s);.

Я пытаюсь импортировать метод S3, predict из другого пакета pls . У меня есть функция, которая использует эти предсказанные значения. Проблема заключается в том, что при компиляции пакета: Error : object 'predict' is not exported by 'namespace:pls' Я собрал эту суть в качестве минимального.

В Go вы не импортируете типы или функции, вы импортируете пакеты (см. Спецификацию: Объявления импорта ).

Пример декларации об импорте:

И , импортируя пакет, вы получаете доступ ко всем его экспортированным идентификаторам, и вы можете ссылаться на них как на packagename.Identifiername , например:

В объявлении импорта есть некоторые хитрости, например,:

Вы можете ссылаться на экспортированные идентификаторы с помощью "m.Identifiername" , например

Вы можете полностью исключить имя пакета:

Но используйте только эти "in emergency" или когда есть коллизии имен (которые редки).

Что @icza сказал выше плюс:

С Go 1.9 существуют псевдонимы типов, которые позволяют импортировать типы из пакетов и псевдонимировать их в то, что выглядит как локальные типы:

Похожие вопросы:

У меня есть посылка под названием A : A/ __init__.py _test.pyx У меня есть источник для другого пакета под названием B : B/ __init__.py _wrapper.pxd _other.pxd _other.pyx _wrapper.pxd wraps a C.

Мой $GOPATH-это /Users/peter/goworkspace Моя текущая версия golang: go version go1.6 darwin/amd64 У меня есть несколько проектов golang под этим рабочим пространством, так что вот структура.

Я пытаюсь импортировать пакет из другого проекта, но он не распознает проект, из которого я пытаюсь импортировать. Я просмотрел различные ответы на этот вопрос (включая python: импорт другого модуля.

Я использую этот код для импорта файла shutdownscheduler.xml из моего пакета, но получаю ошибку: public static Document handler() throws ParserConfigurationException, SAXException, IOException

Я пытаюсь импортировать метод S3, predict из другого пакета pls . У меня есть функция, которая использует эти предсказанные значения. Проблема заключается в том, что при компиляции пакета: Error .

Пожалуйста, примите следующую структуру проекта: /project /packages /files __init__.py fileChecker.py /hasher __init__.py fileHash.py mainProject.py /test Я хотел бы получить доступ к модулю.

У меня есть проект, который опирается на структуру, импортированную из другого пакета, который я назову TheirEntity . В приведенном ниже примере я (кхм) встраиваю TheirEntity в MyEntity , который.

У меня есть структура golang, которая содержит ссылки на некоторые другие структуры. Существует ли автоматизированный способ создания файла .proto из структур ? Например: type A struct < a int b B >.

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