我有一个程序试图在“子类”上实现功能,父类可以在其中检查接口(interface)是否已实现。从角度来看,它实际上是在处理基于是否存在方法的 REST URL 生成。
我遇到的是基于以下模式,IList 和 IGet 接口(interface)都在 TestController 对象上找到,而只有 1 个被实现。当调用 IGet 接口(interface)时,我会感到 panic 。
我宁愿不在基本结构上对 Get/List 进行具体定义,然后必须覆盖它们,宁愿先测试是否存在,然后再从那里开始。
这里还有一个 go playground 链接 https://play.golang.org/p/5j58fejeJ3
package main
import "fmt"
type IGet interface {
Get(int)
}
type IList interface {
List(int)
}
type Application struct {
name string
}
type BaseAppController struct {
*Application
IGet
IList
}
type TestController struct {
*BaseAppController
}
func (ctrl *BaseAppController) Init() {
fmt.Println("In Init")
if f, ok := interface{}(ctrl).(IGet); ok {
fmt.Println("Controller Found GET", f)
} else {
fmt.Println("Controller NOT Found GET", f)
}
if f, ok := interface{}(ctrl).(IList); ok {
fmt.Println("Controller Found LIST", f)
} else {
fmt.Println("Controller NOT Found LIST", f)
}
}
func (ctrl *BaseAppController) Call() {
fmt.Println("In Call")
if f, ok := interface{}(ctrl).(IGet); ok {
fmt.Println("Controller Found GET - going to call", f)
f.Get(7)
} else {
fmt.Println("Controller NOT Found GET - can't call", f)
}
}
// Test controller implements the Get Method
func (ctrl *TestController) Get(v int) {
fmt.Printf("Hi name=%s v=%d\n", ctrl.name, v)
}
func main() {
app := Application{"hithere"}
ctrl := TestController{&BaseAppController{Application: &app}}
ctrl.Init()
ctrl.Call()
}
最佳答案
您似乎缺少的一件事是嵌入接口(interface)如何影响 Go 中的结构。看,嵌入将嵌入类型(结构或接口(interface),无关紧要)的所有方法提升为父类型的方法,但使用嵌入对象作为接收者调用。
实际的副作用是,将接口(interface)嵌入到结构中可以保证该结构实现其嵌入的接口(interface),因为根据定义,它具有该接口(interface)的所有方法。然而,尝试调用任何这些方法而不定义一些东西来填充结构中的接口(interface)字段,将会出现 panic ,因为该接口(interface)字段默认为 nil。
因此,您的类型断言将始终为真。 BaseAppController 嵌入了 IGet 和 IList 接口(interface),因此总是满足这两个接口(interface)。
如果你想要 duck-typing,根据类型上是否存在方法有选择地启用行为,你需要使用类似于标准库 io.WriterTo interface 工作方式的东西。此接口(interface)和 io.ReaderFrom 是可选接口(interface),io.Writer 和 io.Reader 对象可以实现以直接写入或从另一个源读取,而不是 io 包需要缓冲读取数据或要写入的数据本身。
基本要点是您定义一个底层接口(interface),其中包含必需的 方法,这就是您传递的内容。然后您有一个或多个可选接口(interface),您可以检查传递的类型以查看它们是否满足,如果满足,则使用该可选接口(interface)的方法(如果不满足,则恢复为默认行为)。在这种情况下不需要嵌入。
接口(interface)的嵌入,而不是为了鸭子类型,更多的是关于多态性。例如,如果您想访问 SQL 数据库,但又希望能够处理标准数据库调用和事务中的调用,您可以创建一个结构来保存两种类型( sql.DB 和 sql.Tx )的联合方法,例如这个:
type dber interface {
Query(query string, args ...interface{}) (*sql.Rows, error)
QueryRow(query string, args ...interface{}) *sql.Row
Exec(query string, args ...interface{}) (sql.Result, error)
}
然后你做一个这样的结构:
type DBHandle struct {
dber
}
现在,您可以在该sql.DB或sql.Tx中存储结构的dber,以及使用DBHandle的任何内容(以及所有方法(以及所有方法它们是否在事务范围内被调用(但是请记住,必须首先初始化该接口(interface)字段!)
这种类型的功能是嵌入真正开始发挥作用的地方,因为它允许功能和灵 active 接近完全多态继承系统,而无需显式“实现”或“扩展”语句。对于您想要的动态鸭子键入行为类型,它并不是很有用。
关于父结构上的 Golang 嵌入式接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38043678/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问
我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新rubygems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
您将如何构建一个简单的Sinatra应用程序?我正在制作,我希望该应用具有以下功能:“应用程序”更像是一个包含所有信息的管理仪表板。然后另一个应用程序将通过REST访问信息。我还没有创建仪表板,只是从数据库中获取东西session和身份验证(尚未实现)您可以上传图片,其他应用可以显示这些图片我已经使用RSpec创建了一个测试文件通过Prawn生成报告目前的设置是这样的:app.rbtest_app.rb因为我实际上只有应用程序和测试文件。到目前为止,我已经将Datamapper用于ORM,将SQLite用于数据库。这是我的第一个Ruby/Sinatra项目,所以欢迎任何和所有建议-我应
我有一个.pfx格式的证书,我需要使用ruby提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o
我了解instance_eval和class_eval之间的基本区别。我在玩弄时发现的是一些涉及attr_accessor的奇怪东西。这是一个例子:A=Class.newA.class_eval{attr_accessor:x}a=A.newa.x="x"a.x=>"x"#...expectedA.instance_eval{attr_accessor:y}A.y="y"=>NoMethodError:undefinedmethod`y='forA:Classa.y="y"=>"y"#WHATTT?这是怎么回事:instance_eval没有访问我们的A类(对象)然后它实际上将它添加到
我有一个集合选择:此方法的单选按钮是什么?谢谢 最佳答案 Rails3中没有这样的助手。在Rails4中,它是collection_radio_buttons. 关于ruby-on-rails-rails上的ruby:radiobuttonsforcollectionselect,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/18525986/