반응형
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) 까지만 복사해 오는 것을 확인 가능
- 복사된 값은 변형하여도 원본에 영향을 주지 않는 것을 확인 가능 == 값 참조
- 잘라낸 값은 변형하자 원본에 영향을 주는 것을 확인 가능 == 메모리(주소) 참조
반응형