• CELGO 实践 练习


    Hello World

    本文测试基于Google的CEL-GP CodeLab课程,按照所有语言的入门规则,先从一个"hello world"开始。

    配置环境

    func exercise1() {
    	fmt.Println("=== Exercise 1: Hello World ===\n")
    
    	env, err := cel.NewEnv()
    
    	if err != nil {
    
    				glog.Exitf("Error creating CEL environment: %v", err)
    	}
    
    }
    

    CEL应用程序根据环境来评估表达式,使用env,err := cel.NewEnv()来配置标准环境。
    可以通过cel.EnvOption来订制环境,这些选项能够禁用宏、声明自定义变量和函数等。
    一个标注的CEl环境支持语言规范[^1] 当中定义的所有类型、运算符、函数和宏。

    解析并检查表达式

    当配置好环境之后,就可以解析和检查表达式。

    // Compile, eval, profit!
    func exercise1() {
    	fmt.Println("=== Exercise 1: Hello World ===\n")
    
    	// 创建标准环境
    	env, err := cel.NewEnv()
    
    	if err != nil {
    
    				glog.Exitf("Error creating CEL environment: %v", err)
    	}
    
    	// 检查表达式是否编译,返回AST、Issues (Issues定义用于检查解析和检查调用的错误详细信息的方法。)
    	ast,iss := env.Parse(`"Hello, World!"`)
    
    	// 是否存在语法错误
    	if iss.Err() != nil {
    
    		glog.Exitf("Error parsing expression: %v", iss.Err())
    	}
    
    	// 检查表达式的正确性
    	checked,iss := env.Check(ast)
    
    	// 检查是否存在语法错误
    	if iss.Err() != nil {
    
    		glog.Exitf("Error checking expression: %v", iss.Err())
    	}
    
    	// 检查表达式结果类型是否为String
    	if !proto.Equal(checked.ResultType(),decls.String) {
    
    		glog.Exitf("Error: expected result type to be string, got %v", checked.ResultType())
    	}
    
    	// TODO
    }
    

    env.Parseenv.Check返回的iss对象的值可能是错误的问题列表,如果iss.Err()不为nil,那说明表达式的语法或者语义有错误,程序无法继续运行。当表达式格式良好时,这两个调用的结果是一个可执行的cel.Ast
    在这个codelab中解析和检查阶段被打包到当前文件的compile()方法中,它可以用于协助练习其余部分。

    // compile将根据给定的表达式expr进行解析和检查
    // ‘env’确定表达式执行的环境
    // ‘exprType’ 匹配输入表达式结果的ResultType
    func compile(env *cel.Env, expr string, exprType *exprpb.Type) *cel.Ast {
    	ast, iss := env.Compile(expr)
    	if iss.Err() != nil {
    		glog.Exit(iss.Err())
    	}
    	if !proto.Equal(ast.ResultType(), exprType) {
    		glog.Exitf(
    			"Got %v, wanted %v result type", ast.ResultType(), exprType)
    	}
    	fmt.Printf("%s\n\n", strings.ReplaceAll(expr, "\t", " "))
    	return ast
    }
    

    对表达式求值

    一单表达式被解析并检查通过返回一个cel.Ast,代表它可以转换成一个可以求值的表达式程序,其参数绑定和求值模式可以使用cel.ProgramOption选项进行自定义。请注意,也可以使用cel.CheckedExprToAstcelParsedExprToAst函数从proto中读取cel.Ast

    一旦设计好了cel.Program,就可以通过调用Eval对表达式进行求值,求值结果将包含结果、求值详情、错误状态等信息。

    func exercise1() {
    	fmt.Println("=== Exercise 1: Hello World ===\n")
    
    	// 创建标准环境
    	env, err := cel.NewEnv()
    
    	if err != nil {
    
    				glog.Exitf("Error creating CEL environment: %v", err)
    	}
    
    	// 检查表达式是否编译,返回AST、Issues (Issues定义用于检查解析和检查调用的错误详细信息的方法。)
    	ast,iss := env.Parse(`"Hello, World!"`)
    
    	// 是否存在语法错误
    	if iss.Err() != nil {
    
    		glog.Exitf("Error parsing expression: %v", iss.Err())
    	}
    
    	// 检查表达式的正确性
    	checked,iss := env.Check(ast)
    
    	// 检查是否存在语法错误
    	if iss.Err() != nil {
    
    		glog.Exitf("Error checking expression: %v", iss.Err())
    	}
    
    	// 检查表达式结果类型是否为String
    	if !proto.Equal(checked.ResultType(),decls.String) {
    
    		glog.Exitf("Error: expected result type to be string, got %v", checked.ResultType())
    	}
    
    	// 程序生成一个AST的可计算实例
    	program, err := env.Program(checked)
    
    	if err != nil {
    
    		glog.Exitf("Error creating program: %v", err)
    	}
    
    	// 在没有任何附加参数的情况下执行程序
    	out,_,err := eval(program, cel.NoVars())
    
    	if err != nil {
    
    		glog.Exitf("Error evaluating expression: %v", err)
    	}
    
    	// 打印结果
    	fmt.Printf("Result: %v\n", out)
    }
    

    运行这段代码

    run it.

    输出:

    === Exercise 1: Hello World ===
    
    ------ input ------
    (interpreter.emptyActivation)
    
    ------ result ------
    value: Hello, World! (types.String)
    
    Result: Hello, World!
    

    在函数中使用变量

    大多数CEL应用程序会声明可以在表达式中引用的变量。变量的声明指定了名称和类型。变量的类型可以是CEL内置的类型、协议缓冲区的知名类型,或者任何protobuf消息类型,只要它的描述符也被提供给CEL。

    在下面的例子当中,compileevalhelpers方法被作为evn.Parse()/env.Check()/program.Eval()的替身而包含。这些辅助函数是用来打印练习的输入和输出的。

    添加功能

    在此开始使用exercise2的代码

    注解

    [^1]语言规范: https://github.com/google/cel-spec/blob/master/doc/langdef.md

  • 相关阅读:
    DNS原理入门
    软件架构入门
    熵:宇宙的终极规则
    新鲜事
    加密货币的本质
    汇编语言入门教程
    HTML & CSS
    [模板] 矩阵快速幂
    [模板] 三分
    [模板] 2-SAT 问题
  • 原文地址:https://www.cnblogs.com/Zhujianshi/p/16345277.html
Copyright © 2020-2023  润新知