es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo acceder a un campo de una estructura con genéricos (el tipo T no tiene un campo ni un método)?

Me gustaría hacer que el siguiente código compile. Mi comprensión al leer la Propuesta de Parámetros de Tipo (Genéricos en Go) es que esto debería funcionar, pero debe haber algo que me esté perdiendo.

package main

import "fmt"

func main() {
    s := Struct{A: "¡Hola Mundo!"}
    PrintA(s)
}

func PrintA[T Type](v T) {
    fmt.Printf("%s\n", v.A)
}

type Type interface {
    struct{ A string }
}

type Struct struct {
    A string
}

func (s Struct) String() string {
    return s.A
}

El error que obtengo es:

./prog.go:7:8: Struct no implementa Type (posiblemente falta ~ para struct{A string} en la restricción de Type)
./prog.go:11:23: v.A no está definido (el tipo T no tiene el campo o método A)

Me gustaría que T represente todas las estructuras con un campo específico de un tipo específico. Agregar ~ no ayudó.

Aquí hay un ejemplo de la propuesta que fue implementada y forma parte de la última versión beta de Go.

type structField interface {
    struct { a int; x int } |
        struct { b int; x float64 } |
        struct { c int; x uint64 }
}

https://go.dev/play/p/KZh2swZuD2m?v=gotip

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema con el código proporcionado es que la interfaz Type no tiene una restricción de campo. Debería definirse como:

    type Type interface {
        A() string
    }
    

    Además, la función PrintA debe afirmar que v implementa Type para acceder al campo A. Se puede hacer utilizando la sintaxis de aserción de tipo:

    func PrintA[T Type](v T) {
        t, ok := v.(Type)
        if !ok {
            fmt.Println("v no implementa Type")
            return
        }
        fmt.Printf("%s\n", t.A())
    }
    

    Ahora el código se compila y muestra “Hello World!”. El código corregido completo es:

    package main
    
    import "fmt"
    
    func main() {
        s := Struct{A: "Hello World!"}
        PrintA(s)
    }
    
    func PrintA[T Type](v T) {
        t, ok := v.(Type)
        if !ok {
            fmt.Println("v no implementa Type")
            return
        }
        fmt.Printf("%s\n", t.A())
    }
    
    type Type interface {
        A() string
    }
    
    type Struct struct {
        A string
    }
    
    func (s Struct) A() string {
        return s.A
    }
    

    ¡Espero que esto ayude!

Comments are closed.