배열
Go언어에서 배열은 길이가 고정되어 있고, 인덱스는 0부터 시작한다.
var a [5]int // int 형이며 길이가 5인 배열 선언
a[2] = 7 // 배열의 세 번째 요소에 7 대입
fmt.Println(a) // [0 0 7 0 0]
var a [5]int = [5]int{1, 2, 3, 4, 5} // int형이며 길이가 5인 배열을 선언하고 초기화
var b [5]int{1, 2, ,3, 4, 5} // 배열을 선언할 때 자료형과 길이 생략
c := [5]int{1, 2, 3, 4, 5} // 배열을 선언할 때 var 키워드, 자료형과 길이 생략
배열의 크기에 ...을 사용하면 초기화할 값의 개수에 따라 자동으로 크기가 설정된다.
a := [5]int{1, 2, 3, 4, 5} // 배열을 생성하면서 값을 초기화
b := [...]int{1, 2, 3, 4, 5} // 초기화할 요소가 5개이며 ...을 사용했으므로 배열크기는 5로 설정됨
배열 순회
for 인덱스, 값 := range 배열{}
a := [5]int{1 ,2 ,3 ,4, 5}
for i, value := range a { // i에는 인덱스, value에는 배열 요소의 값이 들어감
fmt.Println(i, value)
}
// 실행 결과
0 1
1 2
2 3
3 4
4 5
range 키워드를 사용하면 반복문이 실행될 때마다 배열의 인덱스와 해당 인덱스의 값이 자동으로 변수에 들어간다.
여기서 우리는 배열 요소의 값만 출력하려고 했는데 인덱스 변수 i까지 함께 출력해버렸다. 하지만 다음과 같이 인덱스 변수를 생략하면 첫 번째 리턴값인 인덱스만 들어가므로 주의한다.
a := [5]int{1,2 ,3, 4, 5}
for value := range a { // value에는 값 대신 인덱스가 들어감
fmt.Println(value)
}
// 실행 결과
0
1
2
3
4
인덱스 변수는 생략하고, 값 변수만 사용하려면 다음과 같이 _(밑줄)을 사용하면 된다.
a := [5]int{1, 2, 3, 4, 5}
for _, value := range a { // 인덱스는 생략, value에 배열 요소의 값이 들어감
fmt.Println(value)
}
// 실행 결과
1
2
3
4
5
이처럼 range가 생성하는 인덱스 변수 자리를 밑줄 문자로 대신한다. 그리고 두 번째 리턴값은 올바르게 값 변수에 들어간다.
슬라이스
슬라이스는 배열과 같지만, 길이가 고정되어 있지 않으며 동적으로 크기가 늘어난다. 또한 배열과는 달리 레퍼런스 타입이다.
var a []int // int형 슬라이스 선언
슬라이스는 배열과 달리 안에 길이를 지정하지 않는다. 이렇게 생성된 슬라이스의 길이는 0이다.
슬라이스는 make함수를 사용하여 공간을 할당해야 값을 넣을 수 있다. 여기서 슬라이스 선언과 동시에 make 함수를 사용하면 대괄호와 자료형은 생략할 수 있다. 또한 일반 변수와 마찬가지로 :=를 사용하여 var를 생략할 수 있다.
var a []int = make([]int, 5) // make 함수로 int형에 길이가 5인 슬라이스에 공간 할당
var b = make([]int, 5) // 슬라이스를 선언할 때 자료형과 [] 생략
c := make([]int, 5) // 슬라이스를 선언할 때 var 키워드, 자료형과 [] 생략
a := []int{1, 2, 3, 4, 5} // 슬라이스를 생성하면서 값을 초기화
실제로 슬라이스는 배열을 내장하고 있는데, 이 배열이 더 늘어났을 때 사용할 공간을 미리 할당할 수 있다.
var s = make([]int, 5, 10) // 길이가 5이고 용량이 10인 슬라이스 생성
여기서는 슬라이스 길이는 용량보다 크게 설정할 수 없다. 또한 용량을 생략하면 용량은 길이와 동일하게 설정된다.
- 길이 : 인덱스로 접근할 수 있는 공간이다.(슬라이스 내부 배열의 최대 길이). 용량이 더 확보되어 있더라도 길이 이상의 인덱스에 접근하면 런타임 에러가 발생한다.
- 용량 : 실제 메모리에 할당된 공간이다. 만약 슬라이스에 요소를 추가하여 용량이 가득차면 용량은 자동으로 늘어난다.
미리 슬라이스의 용량을 크게 할당하면 요소가 추가될 때마다 메모리를 새로 할당하지 않아도 되므로 성능상 이점이 있다. 하지만 처음부터 메모리 공간을 많이 차지한다.
반대로 슬라이스 용량을 적게 할당하면 처음부터 메모리 공간은 적게 차지하지만, 요소가 추가될 때 마다 메모리를 새로 할당하게 되므로 성능이 떨어질 수 있다.
슬라이스의 길이는 len함수로 구할 수 있으며, 용량은 cap함수로 구할 수 있다.
a := make([]int 5, 10)
fmt.Println(len(a)) // 길이는 5
fmt.Println(cap(a)) // 용량은 10
단 용량이 길이보다 크더라도 길이를 벗어난 인덱스에는 접근할 수 없다.
a := make([]int, 5, 10) // 길이가 5이면 a[0], a[1], a[2], a[3], a[4]가 생성
fmt.Println(a[4]) // 0: make 함수를 사용하면 슬라이스의 요소는 모두 0으로 초기화
fmt.Println(a[5]) // 길이를 벗어난 인덱스에 접근했으므로 런타임 에러 발생
fmt.Println(a[8]) // 길이를 벗어난 인덱스에 접근했으므로 런타임 에러 발생
// 실행 결과
0
panic: runtime error: index out of range
슬라이스에 값 추가
append 함수를 사용하면 슬라이스의 맨 뒤에 값을 추가할 수 있다.
a := []int{1, 2, 3}
a = append(a, 4, 5, 6)
fmt.Println(a) // [1 2 3 4 5 6]
슬라이스에 다른 슬라이스를 붙이려면 append함수를 사용할 때 ...을 사용한다.
a := []int[1, 2, 3]
b := []int[4, 5, 6]
a = append(a, b...) // 슬라이스 a에 슬라이스 b를 붙일 때는 b...을 쓴다.
fmt.Println(a) // [1 2 3 4 5 6]
레퍼런스 타입
슬라이스는 래퍼런스 타입이다. 내장된 배열에 대한 포인터이므로 슬라이스끼리 대입하면 값이 복사되지 않고 참조(reference)만 한다.
'Golang > Basic' 카테고리의 다른 글
Golang if문에 세미콜론(;) (0) | 2023.03.04 |
---|---|
Golang 헷갈리는 문법 복습 - interface (0) | 2022.02.19 |
Zero 부터 시작하는 Golang - 기본문법3 (0) | 2022.02.19 |
Zero 부터 시작하는 Golang - 기본문법2 (0) | 2022.02.13 |
Zero 부터 시작하는 Golang - 기본문법1 (0) | 2022.02.13 |