Back to archive

Data Structures

Master the essentials of Go data structures, from pointers and structs to the dynamic power of slices. This guide explores how these core building blocks manage memory and organize data efficiently.

StructsPointersArraysSlices

A pointer holds the memory address of a value. `The type *T is a pointer to a T value.Its zero value is nil

	var p *int

The & operator generates a pointer to its operand. The * operator denotes the pointer's underlying value. This is known as "dereferencing" or "indirecting". Unlike C, Go has no pointer arithmetic.

Structs#

Struct fields are accessed using a dot

type Vertex struct{
	x int
	y int
}
func main(){
	v := Vertex{1, 2}
	v.x = 4
	fmt.Println(v.x)
}
print: 4
Pointers to struct#

Struct fields can be accessed through a struct pointer. To access the field x of a struct when we have the struct pointer p Go permits us instead to write just p.x

type Vertex struct{
	x int
	y int
}
func main(){
v := Vertex{1, 2}
p := &v
p.x = 1e9
fmt.Println(v)
}
print: 1000000000 2
Struct Literals#

You can list just a subset of fields by using the Name: syntax.

	type Vertex struct{
	x, y int
	}
	var(
	v1 = Vertex{1,2}
	)

And the order of named fields is irrelevant.

type Vertx struct{
	x, y int
	}
	var(
	v2 = Vertex{y:3,x:4}
	v3 = Vertex{x:1}     //y:0 is implicit
	v4 = Vertex{}        //x:0 y:0 is implicit
	)

The special prefix & returns a pointer to the struct value.

	p=&Vertex{1,2}
	func main(){
	fmt.Println(v1, p, v2, v3)
	}
print: {1 2} &{1 2} {1 0} {0 0}

Arrays#

define#

The type [n]T is an array of n values of type T

	var a [10]int
	func main(){
	var a [2]string
	a[0]="hello"
	a[1]="world"
	fmt.Println(a[0],a[1])
	fmt.Println(a)
	}

feature#

An array's length is part of its type, so arrays cannot be resized.

Slices#

A slice is a view into an underlying array. A slice does not store any data, it just describes a section of an underlying array. Changing the elements of a slice modifies the corresponding elements of its underlying array. Other slices that share the same underlying array will see those changes.

func main() {
	primes := [6]int{2,3,5,7,11,13}
	var s []int = primes[1:4]
	fmt.Println(s)
}
print: {3,5,7}

Slice literals#

A slice literal is like an array literal without the length.

	[3]bool{true, true, false}

And this creates the same array as above, then builds a slice that references it:

	[]bool{true, true, false}

Every non-empty slice must be bacjed by a corresponding underlying array.without this array,the slice has no place to locate the data it manages.When you create a slice using make ( []int,5 ), the Go runtime's memory allocator allocates a block of memory to serve as the underlying array. If you derive a small slice from a massive array,the entire underlying array will not be garbage collected(GC'ed) as long as the slice is still in use.This can potentially lead to a memory leak.

func main() {
	q := []int{2,3,5,7,11,13}
	fmt.Println(q)
	r := []bool{true, false, true, true,false,true}
	fmt.Println(r)
	s := []struct {
	i int
	b bool
	}{
	{2,true},
	{3, false},
	{5, true},
	{7, true},
	{11, false},
	{13, true},
	}
	fmt.Println(s)
}
print: [2 3 5 7 11 13]
[true false true true false true]
[{2 true} {3 false} {5 true} {7 true} {11 false} {13 true}]

Slice defaults#

When slicing you may omit the high or low bounds to use their defaults instead, The default is zero for the low bound the length of the slice for the high bound.

var a [10]int

a[0:10]
a[:10]
a[0:]
a[:]

these slice expressions are equivalent

Slice length and capacity#

Vocabulary List#

Operand:操作数
denote:意味着,代表着
underlying value:实际值,底层值
dereferencing:解引用
indirecting:间接寻址
field:字段
dot:指"."
cumbersome:笨重的、累赘的、低效的
Literal:字面量,常量
subset:子集
Newly allocated:新分配的
lead to:导致
Garbage collected:回收
derive from/create from:从大数组提取小切片一般用dervice(派生)/slice from
memory allocator:术语,内存分配器
backed by:专业表达切片和底层数组的(被....支撑关系)