Внутренние пакеты internal

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

Синтаксис и структура

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

Пример

Давайте создадим структуру проекта с внутренним пакетом:

gomyproject/
├── go.mod
├── main.go
└── internal/
  └── math/
    └── math.go

Пример

Содержимое внутреннего пакета internal/math/math.go:

gopackage math

func Add(a, b int) int {
  return a + b
}

func Sub(a, b int) int {
  return a - b
}

Пример

Использование внутреннего пакета из основного пакета main.go:

gopackage main

import (
  "fmt"
  "myproject/internal/math"
)

func main() {
  res := math.Add(10, 5)
  fmt.Println(res)
}

Результат выполнения кода:

go15

Пример

Попытка импорта внутреннего пакета из внешнего модуля приведет к ошибке компиляции. Например, если другой модуль попытается импортировать myproject/internal/math:

gopackage external

import "myproject/internal/math" // Ошибка: use of internal package not allowed

Пример

Внутренние пакеты можно использовать для организации утилит, которые используются только внутри модуля. Рассмотрим пример с несколькими внутренними пакетами:

gomyproject/
├── go.mod
├── main.go
├── internal/
│   ├── math/
│   │   └── math.go
│   └── helpers/
│     └── helpers.go
└── pkg/
  └── api/
    └── api.go

Пакет pkg/api может импортировать внутренние пакеты, так как находится в том же модуле:

gopackage api

import (
  "myproject/internal/math"
  "myproject/internal/helpers"
)

func Calculate(a, b int) int {
  return math.Add(a, b) + helpers.SomeHelperFunc()
}

Смотрите также

  • экспортированные идентификаторы exported,
    которые доступны из других пакетов
  • неэкспортированные идентификаторы unexported,
    которые доступны только внутри своего пакета
  • область видимости на уровне пакета package-scope,
    которая определяет доступность переменных и функций внутри пакета
  • область видимости на уровне файла file-scope,
    которая ограничивает доступность в пределах одного файла