国内身份证合法需满足:18位字符,前17位为数字,第18位为数字或x/x;地址码和出生日期需在合理范围内;加权校验码须匹配映射表。

身份证号码长度和格式是否合法
国内身份证是18位,前17位为数字,最后一位可能是数字或字母 X(大小写都允许)。光看长度和字符类型不能代替校验,但这是第一道过滤门槛。
常见错误是直接用 len(id) 判断——注意 Go 中 string 是 UTF-8 编码,len() 返回字节数。18 位纯 ASCII 字符刚好 18 字节,但一旦混入 Unicode 字符(比如误粘贴的全角数字),len() 就会出错。
- 用
utf8.RuneCountInString(id)获取真实字符数 - 逐字符检查:前 17 位必须是
'0'–'9',第 18 位只能是'0'–'9'或'X'、'x' - 空字符串、含空格、制表符、中文数字都会在这里被筛掉
地址码和出生日期是否在合理范围内
身份证前 6 位是地址码,中间 8 位是出生日期(YYYYMMDD),这两段不合法,后面加权校验就失去意义。
地址码没有权威实时数据库,但可查公开的行政区划代码表(如民政部 2023 年版),至少排除明显无效值,比如 "999999" 或 "000000";出生日期要能被 time.Parse("20060102", dateStr) 解析,且年份在 1900–2025 之间(避免未来日期或过久远日期)。
- 地址码校验建议缓存一份常用省市区代码(如
"110000"北京市、"310000"上海市),不建议每次 HTTP 请求查库 - 出生日期部分不要只检查是否能 parse,还要验证
dateStr[6:8]是有效日(比如"20230230"能 parse 成 2 月 30 日?不会,time.Parse会返回 error,得捕获 - 注意闰年:2 月 29 日只在闰年有效,
time.Parse会自动处理,无需额外判断
如何计算第 18 位校验码
这才是核心校验逻辑:用前 17 位数字乘以对应权重系数,求和后对 11 取模,再查表映射出校验码。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
权重系数固定为:[7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];模 11 结果与校验码映射为:[1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2](索引 0→1,1→0,2→"X"…10→2)。
- 务必把输入的第 18 位统一转成大写再比对,否则
"x"会判失败 - 前 17 位必须全部是数字,不能用
strconv.Atoi逐个转——效率低,直接用id[i] - '0'得到 0–9 的 int 值更安全 - 加权和可能溢出
int32,建议用int64或直接int(64 位系统足够) - 示例片段:
weights := [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
checkCodeTable := [11]string{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}
sum := 0
for i := 0; i <h3>要不要用第三方库?</h3><p>有现成库如 <code>github.com/chenzhuoyu/idcard</code>,但要注意两点:它不校验地址码有效性,也不做出生日期合理性判断(比如允许 <code>"19000101"</code>),只做加权校验。</p><p>如果你的业务场景要求强校验(比如政务、金融),别依赖单一库;如果只是前端表单快速过滤,用库+基础长度/字符检查也够用。</p><p>真正容易被忽略的是:身份证号可能带前后空格、换行符,或从 PDF 复制时混入零宽字符。实际使用中,<code>strings.TrimSpace()</code> 必须放在最前面,否则 <code>len()</code> 和 <code>utf8.RuneCountInString()</code> 都会误判。</p>golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










