找回密码
 registerss
搜索
查看: 52|回复: 0

[*编程自学*] Lua 可变参数 ... 学习

[复制链接]
  • 打卡等级:本地老炮
  • 打卡总天数:597
  • 打卡月天数:12
  • 打卡总奖励:594
  • 最近打卡:2026-09-15 17:12:42
Waylee 发表于 2026-3-7 15:34 | 显示全部楼层 |阅读模式 | Google Chrome | Windows 10

马上注册,查看网站隐藏内容!!

您需要 登录 才可以下载或查看,没有账号?registerss

×

1) ... 是什么?

... 表示函数接收到的所有“额外参数”(可变参数列表)。

local function f(...)
  print(...)
end

f(1, "a", true)
  • ... 只能在可变参数函数里用(函数形参列表里写了 ...
  • ... 不是 table,它是一种“参数列表”

2) 最常见用法:原样转发参数

写包装函数/Hook 时非常常用:

local function wrap(fn, ...)
  return fn(...)
end

比如你在 skynet 里写一个统一的日志/计时包装,基本都会用到“转发”。


3) 如何拿到第 1 个参数?(常用写法)

把前几个参数显式写出来,剩下的用 ...

local function f(a, b, ...)
  print("a", a, "b", b)
  -- ... 是剩余参数
end

f(10, 20, 30, 40)

4) select:对 ... 做计数、取第 N 个

Lua 标准库里专门给可变参数用的。

4.1 统计参数个数

local function count(...)
  return select("#", ...)
end

print(count())            -- 0
print(count(1,2,3,"x"))   -- 4

4.2 取第 N 个参数

local function third(...)
  return select(3, ...)
end

print(third("a","b","c","d"))  -- c    d(注意:返回第3个到最后所有参数)

如果你只想要“第 N 个单个值”,一般写:

local x = (select(3, ...))

用括号把多返回值“压成 1 个”。


5) 把 ... 变成 table:{...}(但要注意 nil)

local function pack_args(...)
  local t = {...}
  return t
end

关键点:nil 会丢失尾部长度信息

local t = {1, nil, 3}
print(#t)  -- 不可靠(因为数组长度遇到 nil 行为不确定)

如果你要可靠保留 nil 和参数数量,用 table.pack

local function pack(...)
  return table.pack(...)
end

local t = pack(1, nil, 3)
print(t.n)     -- 3
print(t[2])    -- nil 仍然保留

对应解包:

local function unpack_pack(t)
  return table.unpack(t, 1, t.n)
end

6) 多返回值 + ... 的坑(必须掌握)

Lua 里函数可以返回多个值,.../return/赋值位置不同会影响“多返回值是否展开”。

6.1 在最后一个位置会“展开”

local function g() return 1,2,3 end
print(g())          -- 1 2 3
print((g()))        -- 1   (括号会把多返回值压成1个)

6.2 return ... 会把所有参数原样返回

local function id(...)
  return ...
end

print(id(1,2,3))  -- 1 2 3

6.3 把 ... 放进 {...} 会收集成 table(会展开成多个元素)

local function collect(...)
  return {...}
end

7) 实战例子:日志函数(推荐你练)

local function log(fmt, ...)
  print(string.format(fmt, ...))
end

log("x=%d y=%d", 10, 20)

如果你想支持“直接传任意对象”:

local function log_any(...)
  local n = select("#", ...)
  for i = 1, n do
    local v = select(i, ...)
    io.write(tostring(v), i == n and "\n" or "\t")
  end
end

您需要登录后才可以回帖 登录 | registerss

本版积分规则

QQ|手机版|雪舞知识库 ( 浙ICP备15015590号-1 | 萌ICP备20232229号|浙公网安备33048102000118号 )|天天打卡

GMT+8, 2026-9-16 04:26 , Processed in 0.071814 second(s), 26 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表