2.11 Go接口内部实现
Posted 俊king
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.11 Go接口内部实现相关的知识,希望对你有一定的参考价值。
2.11 Go接口内部实现
作用
主要是处理数学当中的函数,根据函数画出函数表达的三维立体图片
示例代码
package main
/* 创建一个算术表达式接口 */
type Expr interface
/* 声明可能的数据类型 */
// Var表示一个变量。如:x
type Var string
// literal表示数字常量。如:3.14
type literal float64
// unary表示一元操作符表达式。如:-x
type unary struct
op rune // "+","-"中的一个
x Expr
// binary表示二元操作符表达式。如:x+y
type binary struct
op rune // "+","-","*","/"中的一个
x, y Expr
// call表示函数调用表达式
type call struct
fn string // pow\\sin\\sqrt函数中的一个
args []Expr
对包含变量的表达式进行求值,需要一个上下文 (environment) 来把变量映射到数值:
// 添加上下文把变量映射到数值
type Env map[Var]float64
让每个表达式提供一个方法来返回表达式在一个给定上下文下的值(因为每个表达式都需要返回所以定义在接口当中):
/* 创建一个算术表达式接口 */
type Expr interface
// 每个表达式都必须都需要返回,所以在接口当中定义该方法
Eval(env Env)float64
具体的Eval
方法。Var
的Eval
方法从上下文中查询结果,如果变量不存在则返回0 literal
的Eval
方法则直接返冋本身的值:
// Var和Eval类型的数据实现接口当中的方法
func (v Var) Eval(env Env) float64
return env[v]
func (l literal) Eval(env Env) float64
return float64(l)
unary
和binary
的Eval
方法首先对它们的操作数递归求值,然后应用op
操作。不把除以 0 或者无穷大当做错误:
// `unary`和`binary`的`Eval`方法首先对它们的操作数递归求值,然后应用`op`操作。不把除以 0 或者无穷大当做错误
func (u unary) Eval(env Env) float64
// switch进行类型断言
switch u.op
case \'+\':
return +u.x.Eval(env)
case \'-\':
return -u.x.Eval(env)
// 抛出异常
panic(fmt.Sprintf("不支持的操作:%q", u.op))
func (b binary) Eval(env Env) float64
// 进行类型断言
switch b.op
case \'+\':
return b.x.Eval(env) + b.y.Eval(env)
case \'-\':
return b.x.Eval(env) - b.y.Eval(env)
case \'*\':
return b.x.Eval(env) * b.y.Eval(env)
case \'/\':
return b.x.Eval(env) / b.y.Eval(env)
// 抛出异常
panic(fmt.Sprintf("不支持的流操作:%q", b.op))
call
方法先对pow
、sin
或者sqrt
函数的参数求值,再调用math
包中的对应函数:
// `call`方法先对`pow`、`sin`或者`sqrt`函数的参数求值,再调用`math`包中的对应函数
func (c call) Eval(env Env) float64
switch c.fn
case "pow":
return math.Pow(c.args[0].Eval(env), c.args[1].Eval(env))
case "sin":
return math.Sin(c.args[0].Eval(env))
case "sqrt":
return math.Sqrt(c.args[0].Eval(env))
// 抛出异常
panic(fmt.Sprintf("不支持的呼叫方法:%s", c.fn))
/*
call 表达式可能会遇到未知的函数,或者参数数量不对。也有可能用“!”或者“<”这类无效的操作符构造了一个 unary 或 binary 表达式
*/
整体代码
package main
import (
"fmt"
"math"
)
/* 创建一个算术表达式接口 */
type Expr interface
// 每个表达式都必须都需要返回,所以在接口当中定义该方法
Eval(env Env)float64
/* 声明可能的数据类型 */
// Var表示一个变量。如:x
type Var string
// literal表示数字常量。如:3.14
type literal float64
// unary表示一元操作符表达式。如:-x
type unary struct
op rune // "+","-"中的一个
x Expr
// binary表示二元操作符表达式。如:x+y
type binary struct
op rune // "+","-","*","/"中的一个
x, y Expr
// call表示函数调用表达式
type call struct
fn string // pow\\sin\\sqrt函数中的一个
args []Expr
// 添加上下文把变量映射到数值
type Env map[Var]float64
// Var和Eval类型的数据实现接口当中的方法
func (v Var) Eval(env Env) float64
return env[v]
func (l literal) Eval(env Env) float64
return float64(l)
// `unary`和`binary`的`Eval`方法首先对它们的操作数递归求值,然后应用`op`操作。不把除以 0 或者无穷大当做错误
func (u unary) Eval(env Env) float64
// switch进行类型断言
switch u.op
case \'+\':
return +u.x.Eval(env)
case \'-\':
return -u.x.Eval(env)
// 抛出异常
panic(fmt.Sprintf("不支持的操作:%q", u.op))
func (b binary) Eval(env Env) float64
// 进行类型断言
switch b.op
case \'+\':
return b.x.Eval(env) + b.y.Eval(env)
case \'-\':
return b.x.Eval(env) - b.y.Eval(env)