¿Es posible usar genéricos para llamar a una función según el tipo de parámetros? Intentaré explicar mi tarea con el mayor detalle posible.
Por ejemplo, tengo una estructura con dos métodos:
package main
import "reflect"
type Cut interface {
int | int8 | int16 | int32 | int64 | float32 | float64 | string
}
type AudioObj struct {
fileName string
}
func (A AudioObj) CutIfFirstIsString(from string, to float64) {
// Cut audio file: ("00:00:03", 81.0)
}
func (A AudioObj) CutIfSecondIsString(from float64, to string) {
// Cut audio file: (0.3, "01:21:00")
}
Y este es mi genérico:
func CutAudio[S Cut, E Cut](MusicFile AudioObj, start S, end E) {
// The first parameter is a string.
if reflect.ValueOf(start).Kind() == reflect.String {
MusicFile.CutIfFirstIsString(start, end)
}
// The second parameter is a string.
if reflect.ValueOf(end).Kind() == reflect.String {
MusicFile.CutIfSecondIsString(start, end)
}
}
Aquí trato de cortar el archivo de audio según el tipo de parámetros de función:
func main() {
audio:= AudioObj{fileName: "music.mp3"}
CutAudio(audio, "00:00:03", 81.0)
CutAudio(audio, 0.3, "01:21:00")
}
Producción:
./prog.go:24:32: cannot use start (variable of type S constrained by Cut) as type string in argument to MusicFile.CutIfFirstIsString
./prog.go:24:39: cannot use end (variable of type E constrained by Cut) as type float64 in argument to MusicFile.CutIfFirstIsString
./prog.go:29:33: cannot use start (variable of type S constrained by Cut) as type float64 in argument to MusicFile.CutIfSecondIsString
./prog.go:29:40: cannot use end (variable of type E constrained by Cut) as type string in argument to MusicFile.CutIfSecondIsString
PlayGround: https://go.dev/play/p/1jx1-vHXDdn
¿Es posible convertir el tipo genérico en el tipo que le envié?
Solución del problema
Puede hacer esto con un buen interruptor de tipo antiguo, pero es un poco detallado:
package main
import (
"fmt"
"strconv"
)
type Cut interface {
int | int8 | int16 | int32 | int64 | float32 | float64 | string
}
type AudioObj struct {
fileName string
}
func (A AudioObj) CutIfFirstIsString(from string, to float64) {
// Cut audio file: ("00:00:03", 81.0)
fmt.Println(`Cut audio file: ("00:00:03", 81.0)`)
}
func (A AudioObj) CutIfSecondIsString(from float64, to string) {
// Cut audio file: (0.3, "01:21:00")
fmt.Println(`Cut audio file: (0.3, "01:21:00")`)
}
func CutAudio[S Cut, E Cut](MusicFile AudioObj, start S, end E) {
// The first parameter is a string.
if _, ok:= any(start).(string); ok {
MusicFile.CutIfFirstIsString(cutToString(start), cutToFloat(end))
}
// The second parameter is a string.
if _, ok:= any(end).(string); ok {
MusicFile.CutIfSecondIsString(cutToFloat(start), cutToString(end))
}
}
func cutToString[S Cut](cut S) string {
var str string
switch start:= any(cut).(type) {
case int:
str = strconv.FormatInt(int64(start), 10)
case int8:
str = strconv.FormatInt(int64(start), 10)
case int16:
str = strconv.FormatInt(int64(start), 10)
case int32:
str = strconv.FormatInt(int64(start), 10)
case int64:
str = strconv.FormatInt(start, 10)
case float32:
str = strconv.FormatFloat(float64(start), 'G', -1, 32)
case float64:
str = strconv.FormatFloat(start, 'G', -1, 64)
case string:
str = start
}
return str
}
func cutToFloat[S Cut](cut S) float64 {
var flt float64
switch end:= any(cut).(type) {
case int:
flt = float64(end)
case int8:
flt = float64(end)
case int16:
flt = float64(end)
case int32:
flt = float64(end)
case int64:
flt = float64(end)
case float32:
flt = float64(end)
case float64:
flt = end
case string:
flt, _ = strconv.ParseFloat(end, 64)
}
return flt
}
func main() {
audio:= AudioObj{fileName: "music.mp3"}
CutAudio(audio, "00:00:03", 81.0)
CutAudio(audio, 0.3, "01:21:00")
}
Enlace del patio de recreo
No hay comentarios:
Publicar un comentario