ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2.11 Go接口内部实现

2022-02-28 10:04:36  阅读:190  来源: 互联网

标签:case return env float64 接口 Eval Go 2.11 op


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方法。VarEval方法从上下文中查询结果,如果变量不存在则返回0 literalEval方法则直接返冋本身的值:

// Var和Eval类型的数据实现接口当中的方法
func (v Var) Eval(env Env) float64 {
   return env[v]
}

func (l literal) Eval(env Env) float64 {
   return float64(l)
}

unarybinaryEval方法首先对它们的操作数递归求值,然后应用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方法先对powsin或者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)
   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`包中的对应函数
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))
}

 

标签:case,return,env,float64,接口,Eval,Go,2.11,op
来源: https://www.cnblogs.com/JunkingBoy/p/15944323.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有