반응형

Go 배열과 슬라이스 차이

I. Array vs Slice

두 데이터 타입 모두 컨테이너의 역할을 하는 것은 동일하지만 아래의 차이가 있음.

  배열(array) 슬라이스(slice)
타입 참조
용량(cap) 수정불가 수정가능
길이(len) 수정불가 수정가능
비교연산 가능 불가능
호출 복사 전달 참조 전달

가변적 특성때문에 슬라이스를 주로 사용하게 됨

  • cap() : 배열/슬라이스 용량
  • len() : 배열/슬라이스 개수

1. 배열/슬라이스 차이 확인

배열

arr1 := [...]int{1, 2, 3, 4, 5, 6, 7} //--> 입력하는 데이터수에 맞게 자동으로 크기 조정
var arr2 [7]int
arr2 = arr1 

arr2[0] = 10

fmt.Printf("1번 배열 :  %v , 1번 배열 메모리 주소 : %p \n", arr1, &arr1)
>>> 1번 배열 :  [1 2 3 4 5 6 7] , 1번 배열 메모리 주소 : 0xc00001a100
fmt.Printf("2번 배열 :  %v , 2번 배열 메모리 주소 : %p \n", arr2, &arr2)
>>> 2번 배열 :  [10 2 3 4 5 6 7] , 2번 배열 메모리 주소 : 0xc00001a140 
fmt.Println(arr1 == arr2)
>>> true
  • 값을 재할당 후 변형하여도 원본은 변하지 않음 == "복사되었다"
  • 두 배열의 비교 연산이 원활하게 실행

슬라이스

slice1 := []int{1, 2, 3, 4, 5}
slice2 := make([]int, 5, 10) //make(자료형, 길이, 용량(생략시 길이와 동일))
var slice3 []int
slice3 = slice1

slice3[0] = 10

fmt.Printf("1번 슬라이스 :  %v , 1번 슬라이스 메모리 주소 : %p , 1번 슬라이스 길이/용량 :%d/%d \n", slice1, &slice1, len(slice1), cap(slice1))
>>> 1번 슬라이스 :  [10 2 3 4 5] , 1번 슬라이스 메모리 주소 : 0xc00000c060 , 1번 슬라이스 길이/용량 : 5/5
fmt.Printf("2번 슬라이스 :  %v , 2번 슬라이스 메모리 주소 : %p , 2번 슬라이스 길이/용량 :%d/%d  \n", slice2, &slice2, len(slice1), cap(slice2))
>>> 2번 슬라이스 :  [0 0 0 0 0] , 2번 슬라이스 메모리 주소 : 0xc00000c080 , 2번 슬라이스 길이/용량 : 5/10
fmt.Printf("3번 슬라이스 :  %v , 3번 슬라이스 메모리 주소 : %p \n", slice3, &slice3)
>>> 3번 슬라이스 :  [10 2 3 4 5] , 3번 슬라이스 메모리 주소 : 0xc00000c0a0
  • 값을 재할당 후 변형하자 원본도 함께 변함 == "참조되었다"
  • 만약 복사를 하고 싶다면 copy 메소드 사용 필요
  • 길이와 용량은 다를 수 있음을 확인 가능

2. 슬라이스 가변 확인

s1 := make([]int, 1, 10)
s2 := []int{6, 7, 8, 9, 10}

s1 = append(s1, 1, 2, 3, 4, 5)
s2 = append(s1, s2...)

fmt.Println(s1)
>>> [0 1 2 3 4 5]
fmt.Println(s2)
>>> [0 1 2 3 4 5 6 7 8 9 10]

s3 := make([]int, 0, 5)
for i := 0; i < 11; i++ {
    s3 = append(s3, i)
    fmt.Printf("%d번째 추가 ==>  길이 : %d  용량 : %d \n", i, len(s3), cap(s3))
}
>>> 
0번째 추가 ==>  길이 : 1  용량 : 5
...
5번째 추가 ==>  길이 : 6  용량 : 10
...
10번째 추가 ==>  길이 : 11  용량 : 20
  • 초기 슬라이스 길이가 1 이기 때문에 "0"이 기본으로 1개 들어가 있는 상태
  • 추가되는 값이 용량을 넘어설 경우 용량이 2배 증가(주의!)

3. 슬라이스 값/주소 참조 확인

s1 := []int{1, 2, 3, 4, 5}
s2 := make([]int, 3)
s3 := s1[0:2] // 슬라이싱

copy(s2, s1)

fmt.Println(s1)
>>> [1 2 3 4 5]
fmt.Println(s2)
>>> [1 2 3]
fmt.Println(s3)
>>> [1 2]

s2[0] = 10
fmt.Println(s1)
>>> [1 2 3 4 5]
fmt.Println(s2)
>>> [10 2 3]
fmt.Println(s3)
>>> [1 2]

s3[0] = 10
fmt.Println(s1)
>>> [10 2 3 4 5]
fmt.Println(s2)
>>> [10 2 3]
fmt.Println(s3)
>>> [10 2]

s1 : 슬라이스 선언, s2 : 복사, s3 : 잘라내기 한 상태

  • s2의 길이가 3이기 때문에 전체를 복사하는 게 아니라, len(3) 까지만 복사해 오는 것을 확인 가능
  • 복사된 값은 변형하여도 원본에 영향을 주지 않는 것을 확인 가능 == 값 참조
  • 잘라낸 값은 변형하자 원본에 영향을 주는 것을 확인 가능 == 메모리(주소) 참조
반응형
복사했습니다!