Just curious, any reason for not going for this?
package main
import "debug/pe"
type inputHeader struct {
b64 *pe.OptionalHeader64
b32 *pe.OptionalHeader32
}
// build the data interface only needed for your logics
func (i *inputHeader) Magic() unit16 {
switch {
case i.b32 != nil:
return i.b32.Magic
case i.b64 != nil:
return i.b64.Magic
}
return 0
}
// build the data interface only needed for your logics.
// Use the largest size for a type.
func (i *inputHeader) SizeOfStackReserve() unit64 {
switch {
case i.b32 != nil:
return uint64(i.b32.SizeOfStackReserve)
case i.b64 != nil:
return i.b64.SizeOfStackReserve
}
return 0 // or handle input error
}
func dump(header *inputHeader) {
// your logic here
magic := header.Magic()
ssr := header.SizeOfStackReserve()
...
}
func main() {
file, err := pe.Open("test.exe")
if err != nil {
panic(err)
}
h := &inputHeader{}
switch x:=file.OptionalHeader.(type) {
case *pe.OptionalHeader64:
h.b64 = x
case *pe.OptionalHeader32:
h.b32 = x
}
dump(h)
}
I’m not questioning the generic existence but do you really need generic for your use case? My reasoning would be:
- You definitely need to sanitize those inputs data from either of the sources anyway so you might as well do it with
interface
processing.
- Your
dump
and magic
business logic are untouched from continuous development point of view (e.g. more parameters introduced in the future).
- You’re working on a debugging tool so clarity is far more important than generic things up magically.
Of course, another way is to import the heavy reflect
package to convert OptionalHeader32
to OptionalHeader64
but I think that’s an overkill.
Also, to answer your question: generic is not yet stable (but coming to be soon), at least for go version 1.17.2. Hence, you still need to stick to conventional Go where you have to define a type in parameter, be it struct or interface (I’m referring to any
).
UPDATE for your generic query:
I don’t think the development reaches there yet. The proposed struct constraint seems to be giving error at the moment (dated October 20, 2021): The Gotip Playground
type customStruct interface {
struct { ID int } | struct { ID uint }
}
prog.go2:20:2: expected '}', found 'struct'
I’m currently based on the accepted proposal documentation here: Type Parameters Proposal. However, I don’t think it will work either. Quote:
For composite types (string, pointer, array, slice, struct, function, map, channel) we impose an additional restriction: an operation may only be used if the operator accepts identical input types (if any) and produces identical result types for all of the types in the type set. To be clear, this additional restriction is only imposed when a composite type appears in a type set. It does not apply when a composite type is formed from a type parameter outside of a type set, as in var v []T
for some type parameter T
.
// structField is a type constraint whose type set consists of some
// struct types that all have a field named x.
type structField interface {
struct { a int; x int } |
struct { b int; x float64 } |
struct { c int; x uint64 }
}
// This function is INVALID.
func IncrementX[T structField](p *T) {
v := p.x // INVALID: type of p.x is not the same for all types in set
v++
p.x = v
}