0Pricing
Lua Academy · บทเรียน

ฟังก์ชัน require

โหลดมอดูลภายนอกด้วย require และทำความเข้าใจการแคชมอดูล

ฟังก์ชัน require เป็นบทเรียน Lua Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 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.lua

require เทียบกับ 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 จะตรวจสอบ preload ก่อน วิธีนี้ทำให้คุณลงทะเบียนโมดูลได้โดยไม่ต้องมีไฟล์ ซึ่งมีประโยชน์สำหรับ 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

การเรียกใช้ require แบบวนรอบ

การพึ่งพากันแบบวนรอบ (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
  • ไฟล์โมดูลส่งคืนส่วนติดต่อสาธารณะของโมดูล (โดยปกติคือ table)
  • ล้างค่า package.loaded[name] เพื่อบังคับให้โหลดใหม่
  • เพิ่มค่าใน package.path เพื่อกำหนดไดเรกทอรีค้นหาแบบกำหนดเอง
  • ใช้ package.preload สำหรับโมดูลในหน่วยความจำ
  • หลีกเลี่ยงการพึ่งพากันแบบวนรอบ

คำถามที่พบบ่อย

บทเรียน “ฟังก์ชัน require” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ฟังก์ชัน require” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Lua Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ฟังก์ชัน require”

โหลดมอดูลภายนอกด้วย require และทำความเข้าใจการแคชมอดูล คุณปฏิบัติ Lua Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Lua Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Lua Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “ฟังก์ชัน require” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Lua Academy นี้ได้ไหม

ได้ บทเรียน Lua Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ฟังก์ชัน require
  2. การเขียนไฟล์มอดูล
  3. package.path และ package.cpath
  4. รูปแบบมอดูลและแนวทางปฏิบัติที่ดี
← กลับไปที่ Lua Academy