我有這樣的界面
type A interface {
SomeMethod()
}
我通過結構指標實作了這個介面:
type Aimpl struct {}
func (a *Aimpl) SomeMethod() {}
我有一個通用函式,它接收一個帶有 A 引數的函式,如下所示:
func Handler[T A](callback func(result T)) {
// Essentially what I'd like to do is result := &Aimpl{} (or whatever T is)
callback(result)
}
另外我應該補充一點,我不能修改A
(它來自庫)的定義。我試過這個:
type MyA[T any] interface{
A
*T
}
但是這段代碼給了我一個錯誤:
func Handler[P any, T MyA[P]](callback func(result A)) {
result := new(P)
callback(result) // result does not implement interface. It's a pointer to a type, not a type
}
此處示例:https ://go.dev/play/p/NVo4plR1R-O
uj5u.com熱心網友回復:
您可以使用型別引數宣告介面,以使其要求實作它的型別是指向其型別引數的指標。
type A[P any] interface {
SomeMethod()
*P
}
有了它,您還需要稍微修改處理程式的簽名。
func Handler[P any, T A[P]](callback func(result T)) {
result := new(P)
callback(result)
}
Handler(func(a *Aimpl) { fmt.Printf("%#v\n", a) })
https://go.dev/play/p/PY5iE7WoHt3
如果您無法修改A
then 的定義,正如您已經發現的那樣,您可以將其包裝成您自己的。
type MyA[P any] interface {
A
*P
}
func Handler[P any, T MyA[P]](callback func(result T)) {
result := new(P)
callback(result)
}
Handler(func(a *Aimpl) { fmt.Printf("%#v\n", a) })
https://go.dev/play/p/50uzqCShnKb
uj5u.com熱心網友回復:
通常,當您撰寫約束時,P any, T MyA[P]
沒有P
實作某個介面的資訊。事實上,實際上P
是任何東西,因為你用any
. T
然后用實體化并產生一個有效的實作者的事實與它本身P
無關P
。對于編譯器,沒有跡象表明*P
(指向任何型別的指標)實作了A
.
如果您想在保留A
回呼簽名的同時完成這項作業,請使用轉換。您仍然需要捕獲基本型別以傳遞非零指標實作器,因此您將介面與指標約束包裝在一起的方法*T
原則上是正確的。
此后使用未命名的約束介面。型別引數的名稱也是反轉的——T
是基本型別并且P
是指標型別(邏輯上......):
func (a *Aimpl) SomeMethod() { fmt.Printf("called, %T, %t\n", a, a == nil) }
func Handler[P interface { *T; A }, T any](callback func(A)) {
p := P(new(T))
callback(p)
}
然后你需要Handler
顯式實體化*Aimpl
:
func main() {
Handler[*Aimpl](func(result A) { result.SomeMethod() })
// prints: called, *main.Aimpl, false
}
游樂場:https ://go.dev/play/p/96_UFVnfyO-
更改回呼型別的另一個選項允許您使用型別推斷而不是顯式實體化,因為那時您已經知道實作者。但在這一點上,尚不清楚如何A
適合圖片:
func main() {
// using the concrete type instead of A
Handler(func(result *Aimpl) { result.SomeMethod() })
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/470407.html