You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Elixir中从ArgumentError获取结构体缺失的强制键?

更优解决方案

方案1:提前校验(推荐)

直接读取结构体模块的@enforce_keys属性,在调用struct!/2前完成校验,既避免异常抛出,又能直接获取缺失键,逻辑清晰且性能更优。

示例代码:

defmodule Foo do
  @enforce_keys [:title, :description]
  defstruct @enforce_keys

  # 封装带校验的构造函数
  def new(attrs) do
    missing_keys = @enforce_keys -- Map.keys(attrs)
    if Enum.empty?(missing_keys) do
      {:ok, struct!(__MODULE__, attrs)}
    else
      {:error, {:missing_keys, missing_keys}}
    end
  end
end

# 使用方式
case Foo.new(%{description: "Lorem ipsum dolor..."}) do
  {:ok, struct} -> struct
  {:error, {:missing_keys, keys}} -> "缺失必填字段:#{inspect(keys)}"
end

优势:

  • 避开异常捕获的性能开销,符合Elixir「显式处理错误」的设计理念
  • 不依赖错误消息的字符串格式,不会因Elixir版本更新失效
  • 可灵活返回自定义错误结构,而非抛出系统异常

方案2:健壮的异常消息解析(适配必须rescue的场景)

若无法修改原结构体模块,必须通过rescue处理,则用正则表达式提取缺失键列表,相比简单字符串分割更稳定。

示例代码:

attributes = %{description: "Lorem ipsum dolor..."}

try do
  struct!(Foo, attributes)
rescue
  e in ArgumentError ->
    case Regex.run(~r/the following keys must also be given when building struct \w+: \[(.+)\]/, e.message) do
      [_, keys_str] ->
        missing_keys = keys_str |> String.split(", ") |> Enum.map(&String.to_atom/1)
        "自定义提示:缺失必填字段 #{inspect(missing_keys)}"
      nil ->
        "发生未知错误:#{e.message}"
    end
end

优势:

  • 无需修改原模块代码,适配无法改动结构体的场景
  • 正则匹配比简单字符串截取更稳定,能兼容多键时的格式变化

内容的提问来源于stack exchange,提问作者Colin Burr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 12:42:20