Можно ли вызвать метод из импортированной библиотеки в другом пакете в Go
Что проверяют
Знаете ли вы правила видимости в Go и как устроены пакеты и модули. Следом обычно уточняют: можно ли добавить метод к типу из чужого пакета и зачем нужен каталог internal.
Как отвечать
Да, если идентификатор экспортирован. Правило одно: имя с заглавной буквы (Parse, Client.Do) видно из других пакетов, со строчной (parse) только внутри своего. Это касается функций, типов, методов, полей структур и констант.
Что стоит добавить к базовому ответу:
- путь импорта и имя пакета: импортируется путь модуля плюс каталог (
github.com/org/lib/client), а обращаются к пакету по имени изpackage, которое не обязано совпадать с каталогом. Для конфликтов есть алиасimport cl "github.com/org/lib/client"; - методы неэкспортируемого типа: если конструктор вернул значение типа
client, его экспортированные методы вызвать можно, хотя сам тип назвать нельзя. Обычно такой API оформляют через интерфейс; internal: пакет изa/internal/xимпортируется только кодом внутри дереваa. Это ограничение компилятора, а не соглашение;- чужой тип не расширить методами: метод для
time.Timeвне пакетаtimeдаст ошибку компиляции. Выход: свой типtype MyTime time.Time(методы исходного типа при этом не переносятся) или встраиваниеtype Client struct{ *http.Client }, где методы продвигаются наружу; - циклы импорта: пакеты
aиbне могут импортировать друг друга, это решается выносом общего кода или интерфейсом на стороне потребителя.
Про модули: зависимость добавляется go get, фиксируется в go.mod и go.sum, для локальной разработки нескольких модулей есть go work или директива replace.
Где спотыкаются
Путают метод и функцию пакета. lib.Do() это функция, а метод вызывается у значения: c := lib.New(); c.Do().
Удивляются, что encoding/json не заполняет поле name. Для пакета json ваша структура чужая, неэкспортируемые поля ему не видны, нужно поле Name с тегом json:"name".
Предлагают go:linkname, чтобы достать неэкспортируемую функцию. Это хак без гарантий совместимости, и новые версии Go заметно ограничили такие ссылки на внутренности стандартной библиотеки.