Downcasting a slice of interfaces to a sub-interface slice [duplicate] - go

This question already has answers here:
Type converting slices of interfaces
(9 answers)
slice of struct != slice of interface it implements?
(6 answers)
Passing a collection of interface types to a function
(1 answer)
Closed 3 years ago.
I'm trying to get better at using interfaces in Go to describe specific functionality, and using interface composition to write better, more understandable code. I ran into this problem which seems like it would be a common use case of go interfaces, yet I can't seem to figure out the proper syntax to use for this application. Here's some code to help explain what I am trying to do:
// Initializable is an interface to an object that can be initialized.
type Initializable interface {
Initialize() error
}
// InitializeAll initializes an array of members.
func InitializeAll(members []Initializable) error {
for _, member := range members {
err := member.Initialize()
if err != nil {
return err
}
}
return nil
}
// Host is an interface to an object providing a set of handlers for a web host.
type Host interface {
Initializable
Hostname() string
RegisterHandlers(router *mux.Router)
}
// ConfigureHosts configures a set of hosts and initializes them.
func ConfigureHosts(hosts []Host) (*mux.Router, error) {
err := InitializeAll(hosts) // compiler error here
}
This is the error: cannot use hosts (type []Host) as type []Initializable in argument InitializeAll.
My initial thought was that I was missing some sort of type downcast, which I know works for single interface objects, but had difficulty casting an array. When I tried doing err := InitializeAll(hosts.([]Initializable)), I got the following error: invalid type assertion: hosts.([]Initializable) (non-interface type []Host on left).
I'd appreciate any ideas as it comes to the design of this code example, and perhaps any suggestions as to proper syntax or some refactoring that I could do to solve this problem. Thanks!

I can't seem to figure out the proper syntax to use for this application
There is no such syntax. You simply cannot do this (directly).

Related

Golang – Testing for interface implementation of underlying value? [duplicate]

This question already has answers here:
How to known a function of a interface is not realized? [duplicate]
(1 answer)
Go reflection with interface embedded in struct - how to detect "real" functions?
(5 answers)
Closed 2 years ago.
So, I was trying to find the solution via the search and web-search. Wasn't successful.
This has likely a simple solution, but probably I'm just a bit messed up.
I have prepared the following example in go playground.
// main.go
type myInterface interface {
Function1() string
Function2() int
}
type notMyStruct struct {
myInterface
// arbitrary implementation
}
func myFunc(val myInterface) {
fmt.Printf("%T %v", val, val)
fmt.Printf("this failes: %q", val.Function1())
// how to safely test,
// whether the underlying value
// has implemented the interface?
}
func main() {
myFunc(&notMyStruct{})
}
It consists of an interface myInterface, an arbitrary struct notMyStruct, which has the embedded interface (but not actually implemented) and some other arbitrary fields.
Now this struct is injected into myFunc, which the go compiler will accept, due to the fact that the interface is embedded.
But if myFunc tries to call a Function of the interface, it panics – understandably.
Assuming, I don't know the actual struct implementation (because I'm not in control of the interface-implementing code):
How can I reliably test, whether a given underlying value has an actual implementation of the method set (Function1 and Function2) defined by the interface?
I assume, this is solvable with reflect package (performance is not an issue here). Maybe there's any other solutions thinkable? Type assertion didn't seem to work out for me...

How to pass type to function argument in Go

ERROR: type CustomStruct is not an expression.
type CustomStruct struct {
}
func getTypeName(t interface{}) string {
rt := reflect.TypeOf(t).Elem()
return rt.Name()
}
getTypeName(CustomStruct)
How can I pass struct type to function without type instance?
This will work
getTypeName((*CustomStruct)(nil))
But I wonder if there is more simple version..
You can't. You can only pass a value, and CustomStruct is not a value but a type. Using a type identifier is a compile-time error.
Usually when a "type" is to be passed, you pass a reflect.Type value which describes the type. This is what you "create" inside your getTypeName(), but then the getTypeName() will have little left to do:
func getTypeName(t reflect.Type) string {
return t.Name()
}
// Calling it:
getTypeName(reflect.TypeOf(CustomStruct{}))
(Also don't forget that this returns an empty string for anonymous types such as []int.)
Another way is to pass a "typed" nil pointer value as you did, but again, you can just as well use a typed nil value to create the reflect.Type too, without creating a value of the type in question, like this:
t := reflect.TypeOf((*CustomStruct)(nil)).Elem()
fmt.Println(t.Name()) // Prints CustomStruct
Lets resurrect this!
The generics proposal for Go got approved, and that's coming, eventually. When this question was first asked, this probably made more sense as a question, but for anyone looking to implement a generics pattern now, I think I've got an alright API for it.
For now, you can't interact with abstract types, but you can interact with methods on the abstract type, and reflect allows you to examine function signatures. For a method, the 0th is the receiver.
type Example struct {int}
type Generic struct{reflect.Type}
func (p Example) Type() {}
func Reflect(generic interface{}) Generic {
real := reflect.TypeOf(generic)
if real.Kind() != reflect.Func || real.NumIn() < 1 {
panic("reflect.Type.In(n) panics if not a func and if n out of bounds")
}
return Generic{real.In(0)}
}
func (g Generic) Make() interface{} {
return reflect.Zero(g.Type).Interface()
}
func main() {
tOfp := Reflect(Example.Type)
fmt.Printf("Name of the type: %v\n", tOfp.Name())
fmt.Printf("Real (initial)value: %v\n", tOfp.Make())
}
Some quick notes:
The structure of "Example" doesn't matter, rather only that it has a method with a non-pointer receiver.
The definition of a type called "Generic" as a struct is to accomplish what I believed OP's actual intent to be.
The above definition of "Generic" is a struct instead of an interface so that it can have its own method set. Defining "Generic" as an interface, and using a methodset specific to each operand-type used with it would make tons of sense.
If you weren't aware, actual generics are coming in Go 1.18. My example above has no linter or compile protection, and will panic at runtime if used incorrectly. It does work, and will let you reason over abstract types while you wait for a native implementation.
Happy Coding!
From Go version 1.18 a new feature Generics has been introduced. In most of the case instead of passing types to function, we can use generics. Then we will also get compile time error instead of runtime error and it's more efficient than reflect also.
Example Code
func HttpGet[T](url, body) T {
var resp T
return T
}
resp := HttpGet[ResponseType]("dummy.example", nil)

How to use a reflect.Type to perform a type assertion [duplicate]

This question already has answers here:
golang type assertion using reflect.Typeof()
(6 answers)
Closed 8 months ago.
I know reflection is generally frowned upon in go but for my current purposes Im pretty sure it is the best solution.
Essentially my project is cli tool which will output an xml query based on incoming commands and return the corresponding result.
There is some boiler plate code for each command request where default values are populated and supplied values validated.
So I have a series of Command objects based on a Command struct as follows:
type Command struct {
Name string
Request interface{}
RequestType reflect.Type
Response interface{}
RegisterFunc func(parentCmd *cobra.Command, cmd *Command) error
}
For the most part I really don't care about the types of the request/response (just xml encode/decode). However I need to briefly cast it to a concrete type to validate with struct annotations
So for example I might do something like this:
var ccReq *CreateCredentialRequest
var set bool
if ccReq, set = command.Request.(*CreateCredentialRequest); !set {
log.Fatal(errors.New("invalid request type"))
}
result, err := govalidator.ValidateStruct(ccReq)
if err != nil {
println("error: " + err.Error())
os.Exit(1)
}
However in an ideal would I would like to handle this generically for all commands, something like this:
var ccReq *CreateCredentialRequest
var set bool
if ccReq, set = command.Request.(command.RequestType); !set {
log.Fatal(errors.New("invalid request type"))
}
However this results in the error:
command.RequestType is not a type
So, how can I store the value of a type for a later type assertion
Note: Following discussion in comments with JimB it seems that i do not actually need the concrete type for validation purposes (interface is fine) but I still need further down to assert the response type to provide a custom response handler
From the reflect.Type docs:
Type values are comparable, such as with the == operator, so they can be used as map keys. Two Type values are equal if they represent identical types.
If you want to compare underlying types, compare the reflect.Type values directly:
if reflect.TypeOf(command.Request) != command.RequestType {
log.Fatal(errors.New("invalid request type"))
}

how to assign only on return value of a function to field of an struct in golang? [duplicate]

This question already has answers here:
Multiple values in single-value context
(6 answers)
Closed 5 years ago.
let's say we have a struct like this:
type Data struct {
a int
}
and we want to get a single return value of a function that returns multiple values and assign it to an object of Data, for example
data := Data {
a: strconv.Atoi("1000")
}
the code above does not work because Atoi returns two value, a number and an error, so we need to handle the extra value (error) somehow, but in my case, I do not need to evaluate error value and it is not possible to dismiss it using _ keyword.
how can I achieve this when initializing a struct, I want to get rid of the error return value
There is no generic way to get just one of returned parameters (Maybe you could implement something with reflect package that returns interface{}).
Other than that it's not good to ignore errors. If you are sure that there's no error implement a helper function like this:
func myAtoi(s string) int {
i, err := strconv.Atoi(s)
if err != nil {
panic(err)
}
return i
}
data := Data {
a: myAtoi("1000")
}

"wrap it in a bufio.NewReader if it doesn't support ReadByte" pattern [duplicate]

This question already has answers here:
What is this "err.(*exec.ExitError)" thing in Go code? [duplicate]
(2 answers)
Closed 7 years ago.
Following is a snippet from one of the Go libs. Could anyone please point out the significance of r.(byteReader)? The syntax usage is not very obvious to a novice. byteReader is a defined interface and does not seem to be the member of io.Reader. Since, this seems to be some kind of nifty code, can anyone provide some insight.
The author mentions: "wrap it in a bufio.NewReader if it doesn't support ReadByte" pattern. https://github.com/dave-andersen/deltagolomb/blob/master/deltagolomb.go
type byteReader interface {
io.Reader
ReadByte() (c byte, err error)
}
func makeReader(r io.Reader) byteReader {
if rr, ok := r.(byteReader); ok {
return rr
}
return bufio.NewReader(r)
}
r.(byteReader) is called a type assertion. Even if io.Reader doesn't implement the byteReader interface in itself, it it still possible that the value stored in r might implement byteReader. So, by doing the type assertion, you can assert if that is the case:
The specification states:
x.(T) asserts that x is not nil and that the value stored in x is of
type T. The notation x.(T) is called a type assertion.
...
If T is
an interface type, x.(T) asserts that the dynamic type of x implements
the interface T.
Edit
The comment, "wrap it in a bufio.NewReader", refers to makeReader's provided io.Reader; if it doesn't implement byteReader, makeReader will wrap it in a bufio.Reader which does implement bytesReader, and return it instead.

Resources