英文:
Can't access function when passing object and catching it in a interface{}
问题
这是我尝试做的事情:
package products
ProductManager struct {
products []*Product
index int64
}
func NewPM() *ProductManager {
return &ProductManager{}
}
func (p *ProductManager) List() []*Product {
return p.products
}
---
var productManager = products.NewPM()
func main() {
api := Api{}
api.Attach(productManager, "/products")
}
func (api Api) Attach(rm interface{}, route string) {
// 将典型的 REST 操作应用到 Mux。
// 例如:Product - 对应 /products
mux.Get(route, http.HandlerFunc(index(rm)))
}
func index(rm interface{}) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// allRecords := rm.List() - 无法调用。找不到方法。
result := reflect.TypeOf(rm) // 可以工作,显示正确的类型。
method := result.Method(0).Name // 也可以工作!显示类型上的一个函数。
w.Write([]byte(fmt.Sprintf("%v", method)))
}
}
为什么我无法在productManager
对象上调用List()
函数?我可以看到类型的函数,甚至在index()
处理程序中获取正确的类型名称。
英文:
Here's what I'm trying to do:
package products
ProductManager struct {
products []*Product
index int64
}
func NewPM() *ProductManager {
return &ProductManager{}
}
func (p *ProductManager) List() []*Product {
return p.products
}
---
var productManager = products.NewPM()
func main() {
api := Api{}
api.Attach(productManager, "/products")
}
func (api Api) Attach(rm interface{}, route string) {
// Apply typical REST actions to Mux.
// ie: Product - to /products
mux.Get(route, http.HandlerFunc(index(rm)))
}
func index(rm interface{}) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// allRecords := rm.List() - DOESN'T WORK. No method found.
result := reflect.TypeOf(rm) // Works, shows me the correct type.
method := result.Method(0).Name // Works as well! Shows me a function on the type.
w.Write([]byte(fmt.Sprintf("%v", method)))
}
}
Any idea on why I can't call the List()
function on my productManager
object? I can see the Type's functions and even get the right Type name in the index()
handler.
答案1
得分: 2
简单来说,rm
是一个空接口变量,因此它没有任何方法,这正是interface{}
的含义:没有方法。如果你知道rm
的动态类型是*ProductManager
,你可以进行类型断言(但这样你可以传递一个*ProductManager
)。也许在长期运行中,你需要对rm
进行类型切换。顺便说一句:几乎总是使用interface{}
都是一个不好的主意。
英文:
Dead simple: rm
is an empty interface variable, so it does not have any methods, that's exactly what interface{}
means: No methods. If you know that rm
's dynamic type is *ProductManager
you can type assert it (but than you could pass a *ProductManager
) Maybe you'll have to type switch on rm
in the longer run. (BTW: using interface{}
is almost always a bad idea.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论