'Facing issue with having generic as return type in Golang

I'm invoking a function from another library whose return signature is defined as under:

(*studentlib.Student[StudentResponse], error)

Student is defined as:

type Student[T any] struct {
    st *students.Student
    xyz *T
}

StudentResponse is defined as:

type StudentResponse struct {
    
}

In my method signature, where I defined the return type as follows:

func abc() (*studentlib.Student[StudentResponse], error) {
   // do something here
}

But for the function return parameters, I keep getting errors like the following:

missing ',' in parameter list

Can someone please help here? What's wrong with the code?



Solution 1:[1]

What version of go are you using? From what I understand, generics weren't available until version 1.18. If you are using version 1.18 or above, I would first off try to give different names to your Student structs. It's a little confusing from a readability standpoint to have multiple structs name Student.

Getting into the issue, I think the biggest problem is that your 'abc' function has no way to know what generic type it needs to return since it's not taking an argument. Also, your 'abc' func needs to have the generic type included in the declaration.

A few smaller issues. Your StudentResponse struct should be an interface instead. Separate the specific data types that you want to included by the '|' char.

With that being said, here is how you would get your code to work:

package main

import (
    "fmt"
)

type Student[T any] struct {
    st string
    xyz T
}

type StudentResponse interface {
    int64 | float64
}

func main() {
    tmp1 := Student[int64]{ // will not throw an error. generic type is defined in StudentResponse
        st: "Testing",
        xyz: 15,
    }
    /*tmp2 := Student[string]{ // will throw an error if used in 'abc' func. generic type not defined in Student Response
        st: "Testing",
        xyz: "15",
    }*/
    
    resp, err := abc(&tmp1)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(resp)
}

func abc[T StudentResponse](s *Student[T]) (*Student[T], error) {
    // do something here
    err := fmt.Errorf("error: %s", "some error") // being used simply to have an error return value
    return s, err
 }

If you want to use a pointer for xyz in student, you could do it this way:

package main

import (
    "fmt"
)

type Student[T any] struct {
    st string
    xyz *T
}

type StudentInfo struct {
    Age float64
    Weight  int64
}

type StudentGrades struct {
    GPA float64
    CreditHours int64
}

type StudentResponse interface {
    StudentInfo | StudentGrades
}

func main() {
    info := StudentInfo{
        Age: 22.5,
        Weight: 135,
    }
    grades := StudentGrades{
        GPA: 3.6,
        CreditHours: 15,
    }
    tmp1 := Student[StudentInfo]{
        st: "tmp1",
        xyz: &info,
    }
    tmp2 := Student[StudentGrades]{
        st: "tmp2",
        xyz: &grades,
    }
    
    resp1, err1 := abc(&tmp1)
    if err1 != nil {
        fmt.Println(err1)
    }

    resp2, err2 := abc(&tmp2)
    if err2 != nil {
        fmt.Println(err2)
    }
    fmt.Println(resp1)
    fmt.Println(resp1.xyz)

    fmt.Println(resp2)
    fmt.Println(resp2.xyz)
}

func abc[T StudentResponse](s *Student[T]) (*Student[T], error) {
    // do something here
    err := fmt.Errorf("error: %s", "some error") // being used simply to have an error return value
    return s, err
 }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1