Golang array of structs and slice of structs: declare, init, iterate

Golang array of structs and golang struct array: [n]T fixed array vs []T slice, golang initialize array of structs with literals or loops, golang make array of structs with make, golang list of structs and go array of structs patterns with range and pointers.

Published

Updated

Read time 3 min read

Reviewed byDeepak Prasad

Golang array of structs and slice of structs: declare, init, iterate

People searching for golang array of structs, golang struct array, go array of structs, or golang list of structs usually want a collection of the same struct type. In Go that is either a fixed-length array [n]Person or, much more often, a slice []Person whose length can change. This guide shows golang initialize array of structs with literals, make for preallocated slices (golang make array style), iteration with range, and field updates—including when a slice of pointers []*Student is clearer. For the struct type itself, see structs in Go; for growing collections, see append to slice; for passing collections to functions, see pass array or slice to a function; for pointers, see Go pointers.

Tested with Go 1.24 on Linux.


Fixed array [n]Struct vs slice []Struct

  • [3]Student: length 3 is part of the type; copying the value copies all three elements.
  • []Student: header with pointer, length, and capacity; append can grow it (see append).

For most “golang array of objects” style lists, use a slice.


golang initialize array of structs (composite literals)

Slice literal (common “golang create array of structs” pattern):

go
package main

import "fmt"

type Student struct {
	Name  string
	Grade int
}

func main() {
	students := []Student{
		{Name: "Alice", Grade: 90},
		{Name: "Bob", Grade: 85},
	}
	fmt.Println(students[0].Name, len(students))
}
Output

You should see Alice 2.

Fixed-size array literal:

go
package main

import "fmt"

type Student struct {
	Name  string
	Grade int
}

func main() {
	team := [2]Student{
		{Name: "Ada", Grade: 99},
		{Name: "Lin", Grade: 94},
	}
	fmt.Println(team[1].Name)
}
Output

You should see Lin.


golang make array of structs (make + assign)

make applies to slices (and maps/channels), not to array types [n]T:

go
package main

import "fmt"

type Student struct {
	Name  string
	Grade int
}

func main() {
	s := make([]Student, 2)
	s[0] = Student{Name: "Mia", Grade: 88}
	s[1].Name = "Noor"
	s[1].Grade = 91
	fmt.Println(s)
}
Output

You should see two structs with the grades you set. Use make([]Student, 0, cap) when you plan to append many rows.


Iterate with range (go array of structs)

go
package main

import "fmt"

type Student struct {
	Name  string
	Grade int
}

func main() {
	students := []Student{
		{"Alice", 90},
		{"Bob", 85},
	}
	for i, st := range students {
		fmt.Println(i, st.Name, st.Grade)
	}
}
Output

You should see two lines with indices 0 and 1. For loop variants, see for loops in Go.


Updating fields: value slice vs []*Student

With []Student, st := range gives a copy; mutating st does not write back unless you assign by index:

go
package main

import "fmt"

type Student struct {
	Name  string
	Grade int
}

func main() {
	students := []Student{{"Ada", 90}}
	students[0].Grade = 95
	fmt.Println(students[0].Grade)
}
Output

You should see 95.

When helpers take *Student and mutate, a pointer slice avoids index noise:

go
package main

import "fmt"

type Student struct {
	Name  string
	Grade int
}

func bump(s *Student) { s.Grade++ }

func main() {
	students := []*Student{
		{Name: "Ada", Grade: 90},
	}
	bump(students[0])
	fmt.Println(students[0].Grade)
}
Output

You should see 91.


Summary

Golang array of structs can mean a true array [n]T or, more often, a slice []T acting as a golang list of structs. Use composite literals for golang initialize array of structs, make([]T, len) when you need allocation first (golang make array), and for range to walk rows. Update fields with index assignment on value slices, or use []*Struct when functions take pointers. Prefer slices unless the length is a fixed part of your model.


References


Frequently Asked Questions

1. What is the difference between a golang array of structs and a slice of structs?

An array has type [n]Student with a fixed length in the type; a slice has type []Student with variable length backed by an array. Most APIs use a slice; use an array when the length is a true compile-time constant part of the type.

2. How do I golang initialize array of structs in one line?

Use a composite literal: students := []Student{{Name: "Alice", Grade: 90}, {Name: "Bob", Grade: 85}} for a slice, or students := [2]Student{{...}, {...}} for a fixed-size array.

3. How does golang make array of structs work?

Call make on a slice type: s := make([]Student, 3) allocates length and capacity 3 with zeroed structs; use a second loop or index assignment to set fields, or make([]Student, 0, 8) then append.

4. Is golang list of structs the same as an array?

People often say list when they mean a slice []T; create and grow it with append or preallocate with make then assign by index.

5. Can I update a struct inside an array or slice?

Yes with index and dot notation: s[i].Name = x for values; for slices of structs you may need s[i].Field = x or a pointer slice []*T if you pass elements to helpers that mutate through pointers.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …