英文:
Golang: Genric struct implement does not match generic interface
问题
我正在尝试使用Go泛型,并遇到了这个问题。为什么Schedule
不能匹配any
?
代码
func demo(m Model[any]) Model[any] {
return m
}
type Model[M any] interface {
FindOne(db *gorm.DB, conds ...any) (m M)
}
type DbOperations[M any] struct{}
func (d DbOperations[M]) FindOne(db *gorm.DB, conds ...any) (m M) {
res := db.First(&m, conds)
if res.Error != nil {
return m
}
return m
}
// 由于这个函数,程序无法编译通过
func a() {
m := DbOperations[Schedule]{}
get(m) // <= 错误发生在这里
}
错误信息
../models/operations.go:103:6: 无法将类型为DbOperations[Schedule]的变量m用作get函数的Model[any]类型参数:
DbOperations[Schedule]未实现Model[any]接口(FindOne方法类型不正确)
具有FindOne(db *gorm.DB, conds ...any) (m Schedule)
期望FindOne(db *gorm.DB, conds ...any) any
英文:
I am experimenting with go generics, and I have encountered this issue. Why is Schedule
not matching any
?
Code
func demo(m Model[any]) Model[any] {
return m
}
type Model[M any] interface {
FindOne(db *gorm.DB, conds ...any) (m M)
}
type DbOperations[M any] struct{}
func (d DbOperations[M]) FindOne(db *gorm.DB, conds ...any) (m M) {
res := db.First(&m, conds)
if res.Error != nil {
return m
}
return m
}
// the program does not compile because of this function
func a() {
m := DbOperations[Schedule]{}
get(m) // <= error occurs here
}
Error message
../models/operations.go:103:6: cannot use m (variable of type DbOperations[Schedule]) as type Model[any] in argument to get:
DbOperations[Schedule] does not implement Model[any] (wrong type for FindOne method)
have FindOne(db *gorm.DB, conds ...any) (m Schedule)
want FindOne(db *gorm.DB, conds ...any) any
答案1
得分: 1
Go语言通常要求你明确指定你使用的类型,并且通常不会自动为你转换变量的类型。所以这段代码不起作用,因为Model[any]
(也就是Model[interface{}]
)和Model[Schedule]
不是相同的类型。(更多细节如下)
你可以尝试将get
函数改为泛型函数:
func get[T any](m Model[T]) Model[T] {
return m
}
然后在调用函数时指定类型:
func a() {
m := DbOperations[Schedule]{}
get[Schedule](m)
}
详细说明
Model[any] != Model[SomeType]
的原因与你不能将字符串切片传递给接受any
切片参数的函数相同:
[]interface{}
切片与[]Schedule
切片具有不同的内存布局。同样,Model[T]
在内存中的布局与Model[any]
也不同。Go语言希望你自己完成它们之间的转换工作。(总结自官方解释和这里的Stack Overflow回答)
英文:
The go language usually requires you to be explicit about the types you're using, and generally does not automatically cast variables for you. So this doesn't work because Model[any]
(aka Model[interface{}]
) and Model[Schedule]
are not the same types. (more details below)
What you could do instead, is also make get
a generic func:
func get[T any](m Model[T]) Model[T] {
return m
}
and then indicate what the type is when you call the func:
func a() {
m := DbOperations[Schedule]{}
get[Schedule](m)
}
Details
Model[any] != Model[SomeType]
for the same reason why you can't pass a string slice to a func that takes an any
slice parameter:
A []interface{}
slice has a different memory layout than a []Schedule
slice. Similarly, a Model[T]
is laid out in memory differently than a Model[any]
. Go expects you to do the work of converting them. (summarizing the official explanation and SO answers here)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论