array
配列の概要
- インデックスアクセス
- 同じ型
- メモリ上の連続した領域に情報を格納
- 固定長
操作
参照
固定長なので & 同じ型
-> 参照するポインタに計算可能
計算式: 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 の確保の仕方