145

I'm newbie in Go. This issue is driving me nuts. How do you init array of structs in Go?

type opt struct {
    shortnm      char
    longnm, help string
    needArg      bool
}

const basename_opts []opt { 
        opt {
            shortnm: 'a', 
            longnm: "multiple", 
            needArg: false, 
            help: "Usage for a"}
        },
        opt {
            shortnm: 'b', 
            longnm: "b-option", 
            needArg: false, 
            help: "Usage for b"}
    }

The compiler said it expecting ; after []opt.

Where should I put the braces { to init my array of struct?

5 Answers 5

187

It looks like you are trying to use (almost) straight up C code here. Go has a few differences.

  • First off, you can't initialize arrays and slices as const. The term const has a different meaning in Go, as it does in C. The list should be defined as var instead.
  • Secondly, as a style rule, Go prefers basenameOpts as opposed to basename_opts.
  • There is no char type in Go. You probably want byte (or rune if you intend to allow unicode codepoints).
  • The declaration of the list must have the assignment operator in this case. E.g.: var x = foo.
  • Go's parser requires that each element in a list declaration ends with a comma. This includes the last element. The reason for this is because Go automatically inserts semi-colons where needed. And this requires somewhat stricter syntax in order to work.

For example:

type opt struct {
    shortnm      byte
    longnm, help string
    needArg      bool
}

var basenameOpts = []opt { 
    opt {
        shortnm: 'a', 
        longnm: "multiple", 
        needArg: false, 
        help: "Usage for a",
    },
    opt {
        shortnm: 'b', 
        longnm: "b-option", 
        needArg: false, 
        help: "Usage for b",
    },
}

An alternative is to declare the list with its type and then use an init function to fill it up. This is mostly useful if you intend to use values returned by functions in the data structure. init functions are run when the program is being initialized and are guaranteed to finish before main is executed. You can have multiple init functions in a package, or even in the same source file.

    type opt struct {
        shortnm      byte
        longnm, help string
        needArg      bool
    }

    var basenameOpts []opt

    func init() { 
        basenameOpts = []opt{
            opt {
                shortnm: 'a', 
                longnm: "multiple", 
                needArg: false, 
                help: "Usage for a",
            },
            opt {
                shortnm: 'b', 
                longnm: "b-option", 
                needArg: false, 
               help: "Usage for b",
            },
        }
    }

Since you are new to Go, I strongly recommend reading through the language specification. It is pretty short and very clearly written. It will clear a lot of these little idiosyncrasies up for you.

Sign up to request clarification or add additional context in comments.

1 Comment

opt is redundant in an array
69

Adding this just as an addition to @jimt's excellent answer:

one common way to define it all at initialization time is using an anonymous struct:

var opts = []struct {
    shortnm      byte
    longnm, help string
    needArg      bool
}{
    {'a', "multiple", "Usage for a", false},
    {
        shortnm: 'b',
        longnm:  "b-option",
        needArg: false,
        help:    "Usage for b",
    },
}

This is commonly used for testing as well to define few test cases and loop through them.

1 Comment

Thank you so much for this. I came across this syntax was getting a bit frustrated that the concept hadn't been introduced in the resource I was reading and that I was having trouble finding the name online.
5

You can have it this way:

It is important to mind the commas after each struct item or set of items.

earnings := []LineItemsType{    
        LineItemsType{    
            TypeName: "Earnings",    
            Totals: 0.0,    
            HasTotal: true,    
            items: []LineItems{    
                LineItems{    
                    name: "Basic Pay",    
                    amount: 100.0,
                },    
                LineItems{    
                    name: "Commuter Allowance",    
                    amount: 100.0,
                },
            },
        },
        LineItemsType{    
            TypeName: "Earnings",    
            Totals: 0.0,    
            HasTotal: true,    
            items: []LineItems{    
                LineItems{    
                    name: "Basic Pay",    
                    amount: 100.0,
                },    
                LineItems{    
                    name: "Commuter Allowance",    
                    amount: 100.0,
                },
            },
        },
    }

Comments

4

I came across this answer while searching for how to initialize a slice of structs. I've been working with Go just a few months myself so I'm not sure if this was true at the time of the question or its just a new update but its not(no longer) necessary to restate the type. See a refactored version of @jimt's example

type opt struct {
    shortnm      byte
    longnm, help string
    needArg      bool
}

var basenameOpts = []opt { 
    {
        shortnm: 'a', 
        longnm: "multiple", 
        needArg: false, 
        help: "Usage for a",
    },
    {
        shortnm: 'b', 
        longnm: "b-option", 
        needArg: false, 
        help: "Usage for b",
    },
}

Comments

0

In Go, if you want to store a list/sequence of structs, you should use a slice. A slice is a dynamically-sized, flexible view into the elements of an array. It's the idiomatic way to handle collections of data in Go.

Example:

package main

import "fmt"

// Define a struct
type Person struct {
    Name string
    Age  int
}

func main() {
    // Create a slice of Person structs
    people := []Person{
        {"Alice", 30},
        {"Bob", 25},
        {"Charlie", 35},
    }

    // Access and manipulate the slice
    for _, person := range people {
        fmt.Printf("%s is %d years old\n", person.Name, person.Age)
    }

    // Adding a new Person to the slice
    newPerson := Person{Name: "Diana", Age: 28}
    people = append(people, newPerson)

    fmt.Println("Updated list of people:")
    for _, person := range people {
        fmt.Printf("%s is %d years old\n", person.Name, person.Age)
    }
}

Key Points:

  • Slice Definition: []Person is a slice of Person structs.
  • Dynamic Size: Slices grow dynamically, which is ideal when you don't know the size of the list in advance.
  • Appending: You can add new elements to a slice using the append function.
  • Iteration: You can iterate over the slice using a for loop.

This is the recommended approach for handling a list of structs in Go.

The example and explanation I provided are based on standard Go language practices and documentation. For more detailed information, you can refer to the official Go documentation:

Go Slices: usage and internals

Go Tour: Structs

Go Documentation: Slice

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.