4장 배열, 슬라이스, 맵
배열
동일한 타입의 원소가 연속된 블록에 저장되는 고정길이 데이터타입. 타입에 따로 제한은 없음.
메모리에 연속적으로 할당됨
선언 방법:
var arr [5]int
선언 이후 타입이나 length 변경 불가능
length 변경이 필요하면 더 큰 배열을 선언하고 원소를 복사해야함.
배열이 초기화되면 각 원소도 타입의 제로 값으로 초기화됨.
array literal로 즉각 초기화 가능
arr := [5]int{1, 2, 3, 4, 5}
배열의 길이가
...
이면 초기화 원소 개수를 기준으로 length 자동 설정arr := [...]int{1, 2, 3}
일부 요소만 특정 값으로 초기화하는 것도 가능
arr := [5]int{1: 10, 3: 30}
배열은 값으로 취급됨. 따라서 같은 타입의 배열이라면 대입도 가능. 대입하면 값의 복사가 이루어짐
함수에 배열을 패러미터로 주면 그 배열의 모든 원소를 복사해서 전달해주게 되므로 상당히 무거운 작업
배열이 필요한 함수라면 배열의 포인터를 받는게 일반적
슬라이스
크기 가변형 데이터 구조. 동적 배열.
사용 중인 메모리의 일부를 잘라내는 것도 가능
배열과 마찬가지로 메모리가 연속적인 블록으로 할당됨
배열을 추상화하여 조작하는 객체. 자체적인 크기는 아주 작음.
length와 capacity를 별도로 관리
capacity는 maximum length
초기화 방법이 여러가지
slice := make([]int, 5)
length만 명시
length와 capacity 명시
슬라이스 리터럴 사용
stringSlice := []string{"Red", "Green", "Blue"}
배열과 거의 비슷하지만 length를 입력하지 않음.
배열처럼 특정 인덱스만 초기화하는 것도 가능
make를 하지 않고 선언하면 nil 슬라이스가 생성됨
에러나 exception이 발생했을 때 주로 생성해서 반환
empty 슬라이스는 make에 length 0 또는 중괄호 안에 아무것도 넣지 않은 슬라이스 리터럴로 생성
slice := make([]int, 0)
slice := []int{}
로직엔 문제가 없는데 결과가 하나도 없을 때 보통 생성해서 반환
슬라이스 활용법
대입은 배열에서 쓰듯이
잘라내기:
newSlice := slice[i:j:k]
i는 새로운 슬라이스의 시작하는 인덱스
중요한건 새로운 슬라이스와 기존 슬라이스 모두 동일한 배열을 참조한다는 것. 따라서 새로운 슬라이스의 값을 변경하면 기존 슬라이스의 값도 변경됨
j는 새로운 슬라이스의 마지막 인덱스 + 1
새로운 슬라이스의 length는 j - i
j는 기존 슬라이스의 length를 초과할 수 없음
k는 capacity를 조절하는 부분으로 생략할 수 있음.
새로운 슬라이스의 capacity는 k - i, 생략할 경우 기존 슬라이스의 capacity - i
k는 기존 슬라이스의 capacity보다 커질 수 없음
append:
newSlice := append(newSlice, 6)
length < capacity 이라면 length를 1 늘리고 해당 인덱스에다가 값 추가
만약에 대상이 잘라낸 slice라면 원본 슬라이스의 값이 바뀌어버릴 수 있음
length >= capacity 이라면 새로운 내부 배열을 생성하고 기존 값들을 복사한 다음 거기에 값 추가
이 때, 새로운 slice의 length는 기존 capacity + 1, capacity는 capacity * 2
원소의 갯수가 1000개 이상이면 capacity는 1.25배씩 증가됨
슬라이스의 length와 capacity를 동일하게 만들면 append로 생겨나는 슬라이스가 새로운 배열을 참조하게 되므로 혼란스러운 상황을 막을 수 있음
range:
for index, value := range slice {}
슬라이스를 순회할 때 사용
중요한 점은 value의 경우 실제 슬라이스의 값을 그대로 쓰는 것이 아니라 복사해서 사용한다는 점이다.
인덱스가 필요없다면 _로 대체 가능
len, cap: len은 length, cap은 capacity 반환
배열과 달리 슬라이스는 함수에 전달될 때 값으로 전달해도 됨.
슬라이스는 포인터, 길이, 용량 필드로 구성된 작은 데이터 객체일 뿐, 실질적인 데이터는 내부 배열에 저장되어있기 때문.
맵
키, 값의 쌍(entry)에 대한 순서 없는 컬렉션을 제공하는 데이터 구조
hashtable 기반으로 구현되어있음
버킷을 고를 땐 LOB 해시
버킷 내부에서 키값을 고를 땐 HOB 캐시
버킷은 해시 데이터를 저장하는 배열 + 키값을 저장하는 배열로 구성
다른 데이터 구조와 초기화 방법은 동일
myMap := make(map[keyType]valueType)
myMap := map[keyType]valueType{key1:value1, key2:value2, key3:value3}
var myMap map[keyType]valueType
맵 활용법
맵에서 값을 조회할 때 존재여부를 함께 알아올 수 있음
value, exists := myMap[key]
exists를 생략하고 값만 받아오면 값의 제로값을 체크해서 존재여부를 확인할 수 있음
range로 다른 데이터 구조랑 비슷하게 순회 가능
함수 전달할 때 슬라이스와 마찬가지로 복사 없이 레퍼런스가 전달됨
Last updated