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로 다른 데이터 구조랑 비슷하게 순회 가능
  • 함수 전달할 때 슬라이스와 마찬가지로 복사 없이 레퍼런스가 전달됨

results matching ""

    No results matching ""