why golang generic type not work for struct with different field [duplicate] - go

This question already has answers here:
Go generics: invalid composite literal type T
(1 answer)
Go generics: Invalid composite literal [duplicate]
(1 answer)
Closed 4 days ago.
type A struct {
x int
}
type B struct {
// x int // this is ok
x string // this comes error below
}
func testG[T A | B]() T {
t := T{} // err: invalid composite literal type T
return t
}
func main() {
testG[A]()
}
when x int in B, it's ok,
when x string in B, error happens: invalid composite literal type T
the difference is only the type x (string / int), how that happens, and why.
hope get some help, thks

Related

cannot use mapToPrint (variable of type map[string]CustomStruct) as type map[string]any - golang [duplicate]

This question already has an answer here:
Gomock cannot use type map[string]*mockFoo as map[string]foo
(1 answer)
Closed 4 months ago.
In my function I was receiving an argument that contained a map for which the value's type was any. I would have thought that any type could therefore be sent, but I got the following error when I tired to use map[string]CustomStruct:
cannot use mapToPrint (variable of type map[string]CustomStruct) as type map[string]any in argument to printMap.
If I create the map with type's value any, everything works, including the assignment of CustomStruct to map values.
Here is a reproducing example:
type CustomStruct struct {
name string
}
func main() {
mapToPrint := make(map[string]CustomStruct, 0)
mapToPrint["a"] = CustomStruct{"a"}
mapToPrint["b"] = CustomStruct{"b"}
printMap(mapToPrint)
}
func printMap(mapToPrint map[string]any) {
for key, value := range mapToPrint {
fmt.Println(key, value)
}
}
go.dev
As the go FAQ says here:
It is disallowed by the language specification because the two types do not have the same representation in memory.
As the FAQ suggests, simply copy the data from your map into a map with value type any, and send it like so to the function:
printableMap := make(map[string]any, len(mapToPrint))
for key, value := range mapToPrint {
printableMap[key] = value
}

How to resolve a Go type error when trying to return an object array in my GRPC service? [duplicate]

This question already has answers here:
Type converting slices of interfaces
(9 answers)
Cannot convert []string to []interface {}
(7 answers)
Cannot use args (type []string) as type []interface {} [duplicate]
(1 answer)
slice of struct != slice of interface it implements?
(6 answers)
Closed 7 months ago.
I'm trying to create a basic GRPC Server in go, but there is a type error that I don't understand how to resolve. A function makes a request to an external API and I would like my GRPC GreetService's Greet function to return the array.
The type error is below:
cannot use result.Inventory (variable of type []InventoryData) as []*proto.DealerInventory_InventoryData value
My GRPC Service's Greet function returns a Proto Buffer message:
func (s *Server) Greet(ctx context.Context, in *pb.GreetRequest) (*pb.DealerInventory, error) {
result := getInventoryData()
return &pb.DealerInventory{
Inventory: result.Inventory,
}, nil
My getInventoryData() should return an array of objects of type DealerInventory:
type InventoryData struct {
DHCost string
DealerNumber string
ModelYear string
ExteriorColor string
InteriorColor string
ModelGroupName string
Transmission string
ModelMSRP string
NumberOnSite uint32
NumberInTransit uint32
}
type DealerInventory struct {
Inventory []InventoryData
Vehiclemodelseriesname string
ZipCodeSent string
}
And my proto message looks like this:
message DealerInventory {
message InventoryData {
string DHCost = 1;
string DealerNumber = 2;
string ModelYear = 3;
string ExteriorColor = 4;
string InteriorColor = 5;
string ModelGroupName = 6;
string Transmission = 7;
string ModelMSRP = 8;
uint32 NumberOnSite = 9;
uint32 NumberInTransit = 10;
}
repeated InventoryData Inventory = 3;
string Vehiclemodelseriesname = 4;
string ZipCodeSent = 5;
}
The type error can be reproduced by cloning the project's example/typeError branch and opening the greet.go file in your IDE.
I'd like to know why I am getting the type error and how I can fix it?
Thanks in advance for your help.
Consider what the error is saying:
./greet.go:12:14: cannot use result.Inventory (variable of type []InventoryData) as type []*"github.com/thanders/dealership-inventory/greet/proto".DealerInventory_InventoryData in struct literal
So this indicates that you are attempting to use a variable of type []InventoryData (where InventoryData is defined defined in package main) as a []*DealerInventory_InventoryData (where DealerInventory_InventoryData is defined in package github.com/thanders/dealership-inventory/greet/proto).
Go will make no attempt to convert between these two structures (by design details like this are not hidden from the developer). This would not work even if the two structs had the same name and fields. For example you cannot do:
x := DealerInventory{IsValidZip: true}
var y pb.DealerInventory
y = x
(this would result in the error cannot use x (variable of type DealerInventory) as type "github.com/thanders/dealership-inventory/greet/proto".DealerInventory in assignment).
If you want to structure your application in this way then you will need to convert between the two data types with something like:
result := getInventoryData()
di := make([]*pb.DealerInventory_InventoryData, len(result.Inventory))
for i, r := range result.Inventory {
di[i] = &pb.DealerInventory_InventoryData{
DHCost: r.DHCost,
DealerNumber: r.DealerNumber,
ModelYear: r.ModelYear,
ExteriorColor: r.ExteriorColor,
InteriorColor: r.InteriorColor,
ModelGroupName: r.ModelGroupName,
Transmission: r.Transmission,
ModelMSRP: r.ModelMSRP,
NumberOnSite: r.NumberOnSite,
NumberInTransit: r.NumberInTransit,
}
}
return &pb.DealerInventory{
IsValidZip: result.IsValidZip,
Dealers: result.Dealers,
Inventory: di,
Vehiclemodelseriesname: result.Vehiclemodelseriesname,
ZipCodeSent: result.ZipCodeSent,
}, nil
Alternatively, consider whether defining a separate InventoryData & DealerInventory in main is providing a benefit (getInventoryData could return a *pb.DealerInventory).

Can I add type parameters to golang methods? [duplicate]

This question already has answers here:
How to solve "interface method must have no type parameters"? [duplicate]
(1 answer)
How to create generic method in Go? (method must have no type parameters)
(2 answers)
Is there a way to map an array of objects in golang?
(1 answer)
Closed 10 months ago.
type Vec[T any] []T
func NewVec[T any](cap int) Vec[T] {
return make([]T, 0, cap)
}
func (v Vec[T]) Len() int {
return len(v)
}
func (v Vec[T]) Map[U any](f func(T) U) Vec[U] {
mapped := NewVec[U](v.Len())
for _, elem := range v {
mapped = append(mapped, f(elem))
}
return mapped
}
this is my code, compiler complain "method must have no type parameters" for the Map method, is there any way to bypass this error?

why cannot use (type func(string)) as type func(interface{}) in assignment [duplicate]

This question already has answers here:
Type func with interface parameter incompatible error
(1 answer)
Func with interface argument not equals to func with string argument. Why?
(1 answer)
Go function types that return structs being used with interfaces
(2 answers)
Passing an arbitrary function as a parameter in Go
(4 answers)
How to convert from `func() *int` to `func() interface{}`? [duplicate]
(1 answer)
Closed 8 months ago.
Please first have a look at the code below.
package main
import "fmt"
type InterfaceFunc func(interface{})
type StringFunc func(string)
func stringFunc(s string) {
fmt.Printf("%v", s)
}
func interfaceFunc(i interface{}) {
fmt.Printf("%v", i)
}
func main() {
var i = interfaceFunc
var s = stringFunc
i = s // I would like someone to explain why this can't be done exactly.
}
Run at https://play.golang.org/p/16cE4O3eb95
Why an InterfaceFunc can't hold a StringFunc while an interface{} can hold a string.
You can not do s = i or i = s, and the reason is both functions are of different type (different signatures), you can not just assign one type with another in golang.
Also type InterfaceFunc func(interface{}) type StringFunc func(string) are sitting there doing nothing.

Is there a way to generically represent a group of similar functions? [duplicate]

This question already has answers here:
Type func with interface parameter incompatible error
(1 answer)
Func with interface argument not equals to func with string argument. Why?
(1 answer)
Go function types that return structs being used with interfaces
(2 answers)
Passing an arbitrary function as a parameter in Go
(4 answers)
How to convert from `func() *int` to `func() interface{}`? [duplicate]
(1 answer)
Closed 8 months ago.
package main
import "fmt"
type Pet interface {
Bark()
}
type Dog int
func (d Dog) Bark() {
fmt.Println("W! W! W!")
}
type Cat int
func (c Cat) Bark() {
fmt.Println("M! M! M!")
}
type AdoptFunc func(pet Pet)
func adoptDog(dog Dog) {
fmt.Println("You live in my house from now on!")
}
func adoptCat(cat Cat) {
fmt.Println("You live in my house from now on!")
}
func main() {
var adoptFuncs map[string]AdoptFunc
adoptFuncs["dog"] = adoptDog // cannot use adoptDog (type func(Dog)) as type AdoptFunc in assignment
adoptFuncs["cat"] = adoptCat // the same as above
}
As the code above, is there a way to use a map or array to collect a bunch of similar functions adoptXxx? If not, what is right pattern to use for this situation?
To use the map as a function collection you'll have to change the signature of your functions to match. func(Pet) is not the same type as func(Dog).
You can re-write AdoptXXX functions to take in Pet and do a type select to ensure correct pet is being input:
func adoptDog(pet Pet) {
if _, ok := pet.(Dog); !ok {
// process incorrect pet type
}
fmt.Println("You live in my house from now on!")
}

Resources