Функция require
Загружайте внешние модули с помощью require и изучайте кэширование модулей.
«Функция require» — бесплатный урок Lua Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Lua Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Lua Academy содержит 4 уроков всего.
Как работает require
require(modname) загружает и возвращает модуль. Он ищет файл .lua в package.path, а библиотеку C — в package.cpath. Результат кэшируется в package.loaded[modname]: последующие вызовы возвращают кэшированное значение, не выполняя файл повторно.
-- First require: loads and executes math_utils.lua
local math_utils = require("math_utils")
-- Second require: returns cached value (file not re-run)
local math_utils2 = require("math_utils")
print(math_utils == math_utils2) -- true (same object)
print(package.loaded["math_utils"] == math_utils) -- trueВозвращаемое значение модуля
Файл модуля должен возвращать значение — обычно таблицу функций. Именно это возвращаемое значение require передаёт вызывающему коду. Если файл ничего не возвращает (или возвращает true), require возвращает это же значение.
-- mymodule.lua:
-- local M = {}
-- function M.hello() print("Hello from module!") end
-- return M
-- In main script:
local m = require("mymodule")
m.hello() -- Hello from module!
-- The module table is the interfaceКэширование в package.loaded
package.loaded — это таблица, сопоставляющая имена модулей с загруженными значениями. Вы можете вручную задать элемент, чтобы предварительно загрузить имитацию, или присвоить ему nil, чтобы принудительно выполнить повторную загрузку (при следующем вызове require файл модуля выполнится заново).
-- Force reload by clearing cache
package.loaded["mymodule"] = nil
local fresh = require("mymodule") -- re-executes the file
-- Preload a mock for testing
package.loaded["db"] = {
query = function() return {} end,
close = function() end,
}
local db = require("db") -- gets the mockФормат package.path
package.path — это список шаблонов, разделённых точками с запятой. Заполнитель ? заменяется именем модуля (точки заменяются разделителями пути). Чтобы добавить каталоги для поиска, можно дописать их в начало package.path.
print(package.path)
-- typically: ./?.lua;./?.luac;/usr/share/lua/5.4/?.lua;...
-- Add local lib directory
package.path = "./lib/?.lua;" .. package.path
-- Now require("utils") will look in ./lib/utils.luarequire, dofile и loadfile
require: кэширует и ищет в package.path. dofile(path): немедленно выполняет файл, не кэширует его и принимает прямой путь. loadfile(path): компилирует, но не выполняет файл, а возвращает функцию. Используйте require для модулей, а dofile — для разовых сценариев.
-- dofile: no caching, direct path
dofile("./scripts/setup.lua")
-- loadfile: compile only, returns function
local fn, err = loadfile("./config.lua")
if fn then
local result = fn() -- execute when ready
end
-- require: best for modules
local json = require("json")require с точками для каталогов
Используйте точки в именах модулей, чтобы обращаться к файлам во вложенных каталогах. require("utils.string") сопоставляется с utils/string.lua (при наличии ? в шаблоне пути). Так организуют библиотеки, состоящие из нескольких файлов.
-- Directory structure:
-- lib/
-- utils/
-- string.lua
-- table.lua
-- init.lua
package.path = "./lib/?.lua;" .. package.path
local strUtils = require("utils.string") -- loads lib/utils/string.lua
local tblUtils = require("utils.table") -- loads lib/utils/table.luaПобочные эффекты инициализации модуля
Файлы модулей выполняются один раз при первом вызове require. Любой код верхнего уровня (вне функций) запускается во время require. Это удобно для одноразовой инициализации, но будьте осторожны: побочные эффекты, такие как сетевые подключения или операции с файлами, выполняются во время импорта.
-- counter.lua:
-- local count = 0 -- initialized once on first require
-- local M = {}
-- function M.increment() count = count + 1 end
-- function M.get() return count end
-- return M
local c = require("counter")
c.increment()
c.increment()
print(c.get()) -- 2
local c2 = require("counter")
print(c2.get()) -- 2 (same instance, cached)Обработка ошибок в require
Если в файле модуля есть синтаксическая ошибка или при загрузке возникает ошибка, require возбуждает ошибку. Сообщение об ошибке содержит имя модуля и ошибку из самого файла. Используйте pcall, чтобы корректно обрабатывать сбои загрузки модуля.
local ok, mod = pcall(require, "possibly_missing")
if not ok then
print("Module not available:", mod)
-- fall back to alternative or default implementation
mod = {feature = function() return "fallback" end}
end
print(mod.feature())package.preload
package.preload — это таблица, в которой можно регистрировать функции загрузки по имени модуля. При вызове require("name") Lua сначала проверяет таблицу предварительной загрузки. Это позволяет регистрировать модули без файлов — полезно для встроенного Lua или тестирования.
package.preload["mymath"] = function()
return {
double = function(n) return n * 2 end,
triple = function(n) return n * 3 end,
}
end
local m = require("mymath")
print(m.double(5)) -- 10
print(m.triple(5)) -- 15Циклическая загрузка
Циклические зависимости (A требует B, B требует A) обрабатываются частично: перед выполнением модуля Lua сохраняет заполненное значением true место в package.loaded. Если B попытается использовать ещё не завершённую таблицу A, результат может оказаться неполным. Избегайте циклических зависимостей при проектировании модулей.
-- a.lua: local b = require("b"); local M = {}; M.name = "A"; return M
-- b.lua: local a = require("a"); print("a.name:", a.name); return {}
-- When a.lua is loaded:
-- 1. a starts executing
-- 2. requires b -> b starts executing
-- 3. b requires a -> gets partial a (still loading!)
-- 4. a.name may be nil at step 3
print("Avoid circular requires in module design")Быстрая проверка
Что происходит при повторном вызове require("mod")?
Повторение: require
Краткое содержание:
require(name)загружает модуль один раз и сохраняет его в кэшеpackage.loaded- Файл модуля возвращает его открытый интерфейс (обычно таблицу)
- Очистите
package.loaded[name], чтобы принудительно загрузить модуль заново - Добавьте пути в
package.path, чтобы указать дополнительные каталоги для поиска - Используйте
package.preloadдля модулей, хранящихся в памяти - Избегайте циклических зависимостей
Часто задаваемые вопросы
Урок «Функция require» бесплатный?
Да — полный текст урока «Функция require» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Lua Academy, подпишись на CoddyKit PRO. Курс Lua Academy содержит 4 уроков всего.
Чему я научусь в уроке «Функция require»?
Загружайте внешние модули с помощью require и изучайте кэширование модулей. Ты практикуешь Lua Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Lua Academy?
Предыдущий опыт не требуется. Lua Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Функция require»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Lua Academy?
Да. Каждый урок Lua Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.