2 回答

TA貢獻1862條經驗 獲得超6個贊
您可以使您的代碼片段工作:
func Transform[T, U any](item T) U {
return any(item).(U)
}
但是如果與 的實際類型不斷言兼容,代碼將因恐慌而失敗:Uitem
這會恐慌:
fmt.Println(Transform[string, int]("foo"))
// Output: panic: interface conversion: interface {} is string, not int
這在沒有恐慌的情況下成功了,因為bytes.Buffer它同時實現了io.Reader和io.Writer接口:
b := &bytes.Buffer{}
_ = Transform[io.Writer, io.Reader](b)
所以,可以做你想做的事。但我不確定它有多大用處,因為實際參數運行時失敗與U.

TA貢獻1866條經驗 獲得超5個贊
T如果您的函數定義為 return ,則無法返回U。即使您斷言Tto U,該函數仍會返回U。
如果你真的想返回or T,U你需要將返回類型聲明為any:
func (s SomeStruct[T, U]) Transform(elem T) any { /* ... */ }
...放棄靜態類型;或者您可以使用“任一”類型的助手:
type Either[T, U any] struct {
value any
}
// Either methods
func (s SomeStruct[T, U]) Transform(elem T) Either[T, U] {
if s.transform == nil {
return Either[T, U]{elem}
}
return Either[T, U]{s.transform(elem)}
}
看看如何在這個 playground中使用它。
備選方案將偏離您的既定目標。一種是實際斷言Tto U,但您必須知道這會返回U,而不是T,即使T它的值可分配給U:
func (s SomeStruct[T, U]) Transform(elem T) U {
if s.transform == nil {
if u, ok := any(elem).(U); ok {
return u
}
return *new(U) // U's zero value if elem assertion fails
}
return s.transform(elem)
}
您必須使用斷言,因為類型參數T和U都受 約束any,因此(理所當然地)沒有其他方式來表達兩者之間的可轉換性。comma-ok 習慣用法有助于避免運行時恐慌。
或者您可以返回(U, error),這通常是合理的做法:
func (s SomeStruct[T, U]) Transform(elem T) (u U, err error) {
if s.transform == nil {
err = errors.New("transform function not set")
return
}
u = s.transform(elem)
return
}
游樂場:https://go.dev/play/p/GKLRmKKWxlP
- 2 回答
- 0 關注
- 137 瀏覽
添加回答
舉報