Reputation: 335
I have an object parsed from some XML file. It has struct type like this
type Report struct {
Items []Item `xml:......`
AnotherItems []AnotherItem `xml:......`
}
type Item struct {
Name string
}
type AnotherItem struct {
Name string
}
func (Item *Item) Foo() bool {
//some code here
}
func (AnotherItem *AnotherItem) Foo() bool {
//another code here
}
For each item i have to do smth like this:
func main(){
//some funcs called to get the report object
doSmth(report.Items)
doSmth(report.AnotherItems)
}
func doSmth(items ????){
for _, item : range items {
item.Foo()
}
}
Since i have different items with same function i want to have only one doSmth
so i can't do just doSmth(items []Item)
And the question is - what should i write instead of "????" to get this working?
The only way i made it to pass report.Items into doSmth() was
func doSmth(items interface{})
But it throws me an error "cannot range over items (type interface {})" And if instead of iteration i just put smth like
func doSmth(items interface{}){
fmt.Println(items)
}
program print the list of my items
Upvotes: 1
Views: 7052
Reputation: 183
You can call like this type of array of struct values using basic array concepts : In this example , []item should be called as item.Item[i].Unitprice
I hope u would got some idea
type UserItem struct {
UniqueID string `json:"uniqueID" bson:"uniqueID,omitempty"`
Item []Item
}
//Item : ""
type Item struct {
ProductName string `json:"productName" bson:"productName,omitempty"`
UnitPrice float64 `json:"unitPrice" bson:"unitPrice,omitempty"`
Quantity float64 `json:"quantity" bson:"quantity,omitempty"`
//main : ""
func main(){
for i := 0; i < len(item.Item); i++ {
SubTotal := item.Item[i].UnitPrice * item.Item[i].Quantity
TotalTax := (item.Item[i].TaxPercentage / 100)
TotalTax = SubTotal * TotalTax
Tax := SubTotal + TotalTax
fmt.Println(Tax)
}
Upvotes: 0
Reputation: 1078
Replace ????
with []Item
: Go Playground. It is just the same as how that variable report.Items
is defined in struct Report
.
Ok, yes that does change the question. The thing I thought of immediately was that you just needed to create an interface such as Itemer
and have []Itemer
in the function definition of doSmth
:
type Itemer interface {
Foo() bool
}
func doSmth(items []Itemer) {
...
}
Unfortunately this does not seem to be possible. I then tried some other permutations including using interface{}
, []interface{}
as well as variadic functions and I couldn't get anything to work.
After doing some research it turns out that Go will not convert the type of slices. Even if each element of a slice is an instance of an interface such as Itemer
or interface{}
it still won't do it. I could not re-find the source but apparently This is due to the fact that a new slice would have to be created and each element would have to be type cast individually from the old slice to the new slice: https://stackoverflow.com/a/7975763/2325784.
To me this suggests that a function such as doSmth
is not possible.
The only thing I could suggest is to restructure the code. If you are willing to post more information about Foo
and doSmth
I can try to help with that.
Upvotes: 1
Reputation: 6872
EDIT: Nvm, this wont work. Forgot about the fact that go doesn't have inheritance.
You could convert the array into a slice, and make the function take a slice as a parameter instead.
names := []string{"leto", "paul", "teg"}
process(names[:])
func process(names []string) {
...
}
Upvotes: 0
Reputation: 11551
You need to use variadic function for this scope:
func main(){
//some funcs called to get the report object
doSmth(report.Items)
}
func doSmth(items ...report.Items){
for _, item := range items {
item.Foo()
}
}
Upvotes: 0