如何使用Golang实现简单表达式计算_Golang基本语法操作实践

发布时间 - 2025-12-31 00:00:00    点击率:
Go标准库无eval,用go/parser+go/constant可安全求值纯数字四则表达式,但不支持变量、函数或逻辑运算;需前置校验输入合法性,支持变量时应改用antonmedv/expr等专用引擎。

Go 语言标准库没有内置表达式求值器,eval 类功能需手动实现或借助第三方包;直接用 go/parser + go/constant 可安全解析简单算术表达式,但不支持变量、函数调用或逻辑运算。

go/parsergo/constant 解析并计算纯数字表达式

这是最轻量、最安全的方案,适用于形如 "2 + 3 * 4""(10 - 2) / 2" 的整数/浮点数四则运算。它绕过字符串拼接执行,避免代码注入风险。

  • 只支持常量表达式(不能含变量、标识符、函数调用)
  • 需将输入包裹成合法 Go 表达式语句,例如加前缀 "const _ = "
  • go/parser.ParseExpr 解析 AST,再用 go/constant.Int64ValFloat64Val 提取结果
  • 整数除法会自动截断,若需浮点结果,确保至少一个操作数带小数点(如 "6.0 / 4"
package main

import ( "fmt" "go/ast" "go/parser" "go/token" "go/constant" )

func evalExpr(s string) (float64, error) { expr, err := parser.ParseExpr("const _ = " + s) if err != nil { return 0, err }

// 确保是二元运算或字面量
tv, err := ast.EvalExpr(token.NewFileSet(), nil, expr)
if err != nil {
    return 0, err
}

switch tv.Kind() {
case constant.Int:
    return constant.Int64Val(tv.Value), nil
case constant.Float:
    return constant.Float64Val(tv.Value), nil
default:
    return 0, fmt.Errorf("unsupported constant kind: %v", tv.Kind())
}

}

func main() { result, _ := evalExpr("2 + 3 * 4") fmt.Println(result) // 14 }

遇到 invalid operationundefined: xxx 错误怎么办

这类错误几乎都源于输入不是合法 Go 常量表达式:

  • undefined: x → 表达式里写了变量名(如 "x + 1"),而 go/parser 不做变量绑定
  • invalid operation: operator + not defined on string → 输入含未加引号的字符串字面量(如 "hello + world"),应只传数字和运算符
  • syntax error: unexpected newline → 字符串含换行或注释,需提前清理(strings.TrimSpace + 去掉 ///* */
  • 空字符串或只有空格 → ParseExpr 直接返回语法错误,建议前置校验 len(strings.TrimSpace(s)) == 0

需要支持变量时,别硬改 go/parser,换用 antonmedv/expr

go/parser 天然不支持运行时变量代入,强行在 AST 上做符号表替换极易出错且破坏类型安全。更现实的做法是引入轻量表达式引擎:

  • github.com/antonmedv/expr 支持变量、布尔逻辑、比较、基础函数(len, round),语法接近 Go 但更宽松
  • 它仍不执行任意代码(无 exec、无反射调用),安全性可控
  • 性能比 go/parser 略低,但对千次/秒以下的计算场景无感
  • 注意:默认禁止访问结构体字段(如 user.Name),需显式启用 expr.Env 并传入允许的字段名列表
import (
    "fmt"
    "github.com/antonmedv/expr"
)

func main() { env := map[string]interface{}{"a": 5, "b": 3} code := "a * b + 2" program, := expr.Compile(code) output, := expr.Run(program, env) fmt.Println(output) // 17 }

真正麻烦的不是写个计算器,而是决定「哪些东西必须禁止」:用户输入是否可能含恶意构造(如超深递归、超长数字、科学计数法溢出)?是否要限制执行时间?这些边界问题比语法解析本身更消耗精力。


# git  # go  # github  # golang  # ai  # switch  # 标准库  # String  # 常量  # 运算符  # Error  # 标识符  # const  # 字符串  # 结构体  # 递归  # operator  # len  # undefined  # 但不  # 这是  # 浮点  # 求值  # 适用于  # 执行时间  # 这类  # 布尔  # 写了 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 高防服务器租用如何选择配置与防御等级?  Laravel怎么发送邮件_Laravel Mail类SMTP配置教程  利用 Google AI 进行 YouTube 视频 SEO 描述优化  简单实现Android验证码  如何在宝塔面板创建新站点?  如何快速搭建个人网站并优化SEO?  昵图网官方站入口 昵图网素材图库官网入口  想要更高端的建设网站,这些原则一定要坚持!  如何用景安虚拟主机手机版绑定域名建站?  大连网站制作公司哪家好一点,大连买房网站哪个好?  如何在VPS电脑上快速搭建网站?  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  C++时间戳转换成日期时间的步骤和示例代码  INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】  如何快速上传建站程序避免常见错误?  如何制作一个表白网站视频,关于勇敢表白的小标题?  Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】  制作旅游网站html,怎样注册旅游网站?  详解MySQL数据库的安装与密码配置  长沙做网站要多少钱,长沙国安网络怎么样?  详解Android图表 MPAndroidChart折线图  北京网页设计制作网站有哪些,继续教育自动播放怎么设置?  文字头像制作网站推荐软件,醒图能自动配文字吗?  iOS中将个别页面强制横屏其他页面竖屏  Laravel如何配置Horizon来管理队列?(安装和使用)  标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?  香港服务器建站指南:免备案优势与SEO优化技巧全解析  济南网站建设制作公司,室内设计网站一般都有哪些功能?  Laravel如何实现邮件验证激活账户_Laravel内置MustVerifyEmail接口配置【步骤】  Laravel如何实现本地化和多语言支持?(i18n教程)  Laravel怎么实现支付功能_Laravel集成支付宝微信支付  mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?  javascript中闭包概念与用法深入理解  油猴 教程,油猴搜脚本为什么会网页无法显示?  Laravel Debugbar怎么安装_Laravel调试工具栏配置指南  微信h5制作网站有哪些,免费微信H5页面制作工具?  广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?  Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  如何在IIS7中新建站点?详细步骤解析  Laravel如何创建自定义中间件?(Middleware代码示例)  香港服务器如何优化才能显著提升网站加载速度?  Laravel如何配置任务调度?(Cron Job示例)  香港服务器租用每月最低只需15元?  Laravel的辅助函数有哪些_Laravel常用Helpers函数提高开发效率  Android中AutoCompleteTextView自动提示  Laravel怎么实现模型属性的自动加密  微信小程序 配置文件详细介绍  Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧  Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】