aloneibreak
aloneibreak

Reputation: 335

Passing array of structs to a function in Go

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

Answers (4)

Kevin007
Kevin007

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

JamesStewy
JamesStewy

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

Olian04
Olian04

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

Endre Simo
Endre Simo

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

Related Questions