개발바닥

슬라이스(Slice) 본문

GO 언어

슬라이스(Slice)

라이언 2022. 2. 26. 20:14
반응형

슬라이스(Slice) 란?

Go 배열은 고정된 배열크기 안에 동일한 타입의 데이터를 연속적으로 저장하지만, 배열의 크기를 동적으로 증가시키거나 부분 배열을 발췌하는 등의 기능을 가지고 있지 않다.

Go Slice는 동적 배열 타입(배열을 가리키는 포인터 타입)이다. 배열과 달리 고정된 크기를 미리 지정하지 않을 수 있고, 차후 그 크기를 동적으로 변경할 수도 있고, 또한 부분 배열을 발췌할 수도 있다.

 

용어 정리!
정적(Static) : 컴파일 시점(Compile)에 결정
동적(Dynamic) : 실행 시점(Runtime)에 결정

배열과 슬라이스 선언 비교

var v [10]int // 길이가 10인 int형 배열
var s []int // int형 슬라이스 선언
s2 := make([]int, 5, 10) // len 5, cap 10 인 슬라이스 생성 (Zero value 슬라이스를 만든다.)

슬라이스를 만드는 방법은 2가지가 있다.

make() 함수를 사용해서 만드는 방법과 배열 선언하듯이 길이를 선언하지 않고 만드는 방법이 있다.

두 방법에는 차이점이 있다.

make() 함수를 이용하게 되면 make([]type타입, len길이, cap용량)으로 만들게 되면 Zero value인 슬라이스가 만들어지게 된다.

여기서 세번째 cap 용량을 생략하게 되면 cap는 len과 같은 값을 갖는다. 

슬라이스에 별도의 길이와 용량을 지정하지 않으면 기본적으로 길이와 용량이 0인 슬라이스를 만든다.

이를 Nil Slice라고 한다. (nil과 비교하면 true로 나온다.)

여기서 잠깐!
Go언어에서 Zero value란?
초기화시 초기 값을 선언을 안하게 되면 zero value를 가진다.
int : 0  
float : 0.0
bool : false
string : ""
function, pointer, map, channel, slice, interface : nil

슬라이스는 배열을 가리키는 포인터 타입

package main

import "fmt"

func changeArr(arr [3]int) {
	arr[1] = 10
	fmt.Println("chane func arr : ", arr)
}

func changeSlice(s []int) {
	s[1] = 10
	fmt.Println("chane func slice : ", s)
}

func main() {
	v := [3]int{1, 2, 3} // 배열 생성
	s := []int{1, 2, 3} // 슬라이스 생성

	changeArr(v)
	changeSlice(s)
	fmt.Println("main arr : ", v)
	fmt.Println("main slice : ", s)
}

결과 내용

chane func arr :  [1 10 3]
chane func slice :  [1 10 3]
main arr :  [1 2 3]
main slice :  [1 10 3]

보다시피 메인에 출력을 하게 되면 슬라이스는 값이 변경된 것을 확인할 수 있다.

여기서 알 수 있듯이 슬라이스는 배열을 가리키는 포인터 타입이다. 즉 포인터 주소를 넘겨주므로 메인에 변경된 값이 보인다. 

즉, 배열은 call by value 이고, 슬라이스는 call by reference이다.

 

용어 정리!
call by value는 인자로 받은 값을 복사하여 처리를 한다. (값을 복사하여 처리)
call by reference는 인자로 받은 값의 주소를 참조하여 직접 값에 영향을 준다. (직접 참조)

len과 cap

슬라이스는 배열과 다르게 len과 cap을 가진다. 

len은 현재 슬라이스에서 사용중인 길이를 의미

cap은 현재 슬라이스의 총 크기(사용중인 길이 + 비어있는 길이)를 의미

 

슬라이싱

배열의 일부를 잘라내어 슬라이스를 만드는 것을 슬라이싱이라고 한다.

array[startIndex:endIndex]

위 코드는 array이라는 배열에서 startIndex부터 endIndex - 1 까지 자르겠다는 의미이다.

여기서 주의할 점은 반환된 Slice의 cap은 startIndex부터 array 배열의 마지막 길이까지가 된다.

 

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	s2 := s[3:7]
	fmt.Println(" len : ", len(s2), " cap : ", cap(s2), " s2 value : ", s2)
}

결과 내용

 len :  4  cap :  7  s2 value :  [4 5 6 7]

 

반응형

'GO 언어' 카테고리의 다른 글

인터페이스 (interface)  (0) 2022.03.06
모듈(Module)  (0) 2022.03.06
구조체(Struct)  (2) 2022.02.28
채널(Channel)  (0) 2022.02.22
고루틴(goroutine)  (0) 2022.02.21
Comments