配列の概要

  • インデックスアクセス
  • 同じ型
  • メモリ上の連続した領域に情報を格納
  • 固定長

操作

参照

固定長なので & 同じ型
-> 参照するポインタに計算可能

計算式: target = base + size x index

-> O(1)

index について

Q. なぜ 0 index なのか
A. 計算効率の最大化
1 index であると計算がずれてしまうため

挿入・削除

配列の最後の値に対して操作場合には O(1) でアクセスし、操作可能

一方、先頭の場合は?
最後の要素までそれぞれずらす必要がある
-> O(n)

以上から、配列はアクセス(特にランダムアクセス)が頻繁に行われるようなユースケースに適している。
一方、挿入・削除の操作が頻繁に行われるユースケースには適さない。

Code

package main

import (
	"fmt"
	"reflect"
)

func main() {

	arr := [5]int{1, 2, 3, 4, 5}

	fmt.Println(arr)
	fmt.Println("arr[1]:", arr[1])

	arr[2] = 9
	fmt.Println(arr)

	// fmt.Println(arr[5]) will "invalid argument: index 5 out of bounds [0:5]"
	// arr[5] = 10 // will display "invalid argument: index 5 (constant of type int) out of bounds [0:5]"

	// arr[4] = 8.5 will desplay "cannot use 5.5 (untyped float constant) as int value in assignment (truncated)"
	arr[4] = 8.0 // float will be truncated to int

	// arr[3] = "a" will display "cannot use "a" (untyped string constant) as int32 value in assignment"
	arr[3] = 'a' // rune is an alias for int32 https://pkg.go.dev/builtin#rune
	fmt.Println(arr)

	intMemSize := reflect.TypeOf(9).Size()
	floatMemSize := reflect.TypeOf(8.5).Size()
	runeMemSize := reflect.TypeOf('a').Size()
	stringMemSize := reflect.TypeOf("a").Size()

	fmt.Printf("Memory size of int:   %10v bytes\n", intMemSize)
	fmt.Printf("Memory size of float: %10v bytes\n", floatMemSize)
	fmt.Printf("Memory size of rune:  %10v bytes\n", runeMemSize)
	fmt.Printf("Memory size of string:%10v bytes\n", stringMemSize)

	for index, value := range arr {
		fmt.Printf("Index: %2d Value: %2d Pointer: %#+10p\n", index, value, &value)
	}
}

Todo

  • slice との比較
  • slice の len, cap の確保の仕方