파이문

Go 튜토리얼 - 배열, 슬라이스 본문

Go/Tutorial

Go 튜토리얼 - 배열, 슬라이스

민Z 2017. 1. 30. 00:21

Go 배열

(Golang array)



모든 배열은 연속된 메모리 주소로 되어 있습니다. Go 역시 마찬가지 입니다.

Go에서 배열을 정의하려면, 요소의 타입과 요소의 개수를 명시해야 합니다. 

var variable_name [SIZE] variable_type

배열의 크기는 반드시 integer이며, 0보다 커야 합니다. 타입은 Go에서 가능한 어떤 타입도 올 수 있습니다. 예를 들어서 10개의 요소를 갖는 float32 타입의 배열을 정의하고자 한다면 아래 처럼 할 수 있습니다.

var balance [10] float32

초기화 시 여러개의 값을 임의로 넣고자 한다면 중괄호 안에 값을 채우면 됩니다. 또한 특정 위치에 다른 값을 설정하고 싶다면 다른 언어처럼 index 값으로 접근하여 값을 대입하면 됩니다.

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0

balance[4] = 50.0 


Go 슬라이스

(Golang slice)



슬라이스는 배열의 일부이며 정의할 때는 배열의 크기를 지정하지 않거나, make 함수를 통해서 할 수 있습니다.

var x1 []float64 // 첫번째 방법
x2 := make([]float64, 5) // 두번째 방법

이렇게 하면 float64 타입인 슬라이스 x1와 길이 5를 갖는 슬라이스 x2가 생성됩니다. make 함수인 경우 세번째 매개변수에 값이 올 수 있는데, capactiy를 의미합니다.  

x1 := make([]int, 5, 10)  
x2 := make([]int, 5)   
x3 := [5]int{}

x1의 경우 length 가 5이고, capacity가 10을 의미하는 슬라이스이며, x2는 length와 capacity 모두 5를 의미합니다. 마지막으로 x3의 경우는 length가 5인 슬라이스가 됩니다.


슬라이스는 capacity를 넘어, 아이템을 추가하면 새로운 슬라이스를 생성하게 됩니다. 아래의 예제를 보면 length가 0이며 capacity가 5인 슬라이스를 생성해, 20번 append를 시도합니다. length는 0에서 20으로 증가하지만 capacity는 그렇지 않습니다. 지정한 capacity를 초과하면 새로운 슬라이스를 생성하게 되지요. (그러므로 length는 항상 capacity 보다 작거나 같아야 합니다.)


  • length : 인덱스로 접근할 수 있는 공간입니다. capacity가 확보되어 있더라고 length 이상의 인덱스에 접근하면 런타임 에러가 발생합니다.
  • capacity: 실제 메모리에 할당된 공간입니다. 만약 슬라이스에 요소를 추가하여 capacity가 가득차면 자동으로 늘어납니다.
package main

import "fmt"

func main() {
	slice := make([]int, 0, 5)
	for i := 0; i < 20; i++ {
		slice = append(slice, 1)
		fmt.Println(len(slice), " ", cap(slice))
	}
}

출력 결과는 아래와 같습니다.

1   5
2   5
3   5
4   5
5   5
6   10
7   10
8   10
9   10
10   10
11   20
12   20
13   20
14   20
15   20
16   20
17   20
18   20
19   20
20   20

더 자세한 설명은 이 블로그에서 확인할 수 있습니다.


부분 슬라이스를 정의하자면 파이썬에서 리스트와 마찬가지로 인덱스에 [lower bound: upper bound] 를 명시하면 됩니다. 

package main

import "fmt"

func main() {
	numbers := []int{0,1,2,3,4,5,6,7,8}
	printSlice(numbers)

	fmt.Println("numbers ==", numbers)

	fmt.Println("numbers[1:4] ==", numbers[1:4])

	fmt.Println("numbers[:3] ==", numbers[:3])

	fmt.Println("numbers[4:] ==", numbers[4:])

	numbers1 := make([]int,0,5)
	printSlice(numbers1)

	number2 := numbers[:2]
	printSlice(number2)

	number3 := numbers[2:5]
	printSlice(number3)

}

func printSlice(x []int){
	fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

출력은 아래처럼 나오게 됩니다.

len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8]
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]
numbers[4:] == [4 5 6 7 8]
len=0 cap=5 slice=[]
len=2 cap=9 slice=[0 1]
len=3 cap=7 slice=[2 3 4]

가장 먼저 만든 numbers 슬라이스는 make가 아닌 사이즈를 명시하지 않고 생성하였고, 그렇기 때문에 전체 슬라이스의 크게인 9로 length와 capacity가 출력됩니다. (capacity를 명시하지 않으면 length와 같기 때문이죠.) 


이후에 출력되는 numbers[1:4]는 numbers의 첫번째 인덱스 부터 세번째 인덱스까지 출력되고, 인덱스 값을 명시하지 않으면 lower bound는 0, upper bound는 length 입니다.


그리고 numbers1은 make를 통해 슬라이스를 정의하였는데요, 두번째 파라미터는 length이기 때문에 length는 0이고 세번째는 앞서 말했듯이 capacity이기에 5가 출력됩니다.


numbers2는 numbers의 0번째 인덱스부터 1번째 인덱스 까지로 길이는 두 개의 element를 갖고 있으므로 2이며, 1번째 인덱스 부터 마지막 인덱스까지가 capacity가 되어 9를 출력합니다.


numbers3 역시 numbers의 2번째 인덱스부터 4번째 인덱스 까지로 길이는 3이고 2번째 인덱스인 2부터 8까지 갖고 있으므로 capacity는 7입니다.


마지막으로 빈 슬라이스는 nil을 리턴하기 때문에 비어있음을 확인하려면 slice == nil을 하면 됩니다.



참고

http://stackoverflow.com/questions/32391147/golang-make-function-and-third-param/32391217

https://www.tutorialspoint.com/go/go_slice.htm

'Go > Tutorial' 카테고리의 다른 글

Go 튜토리얼 - switch 문  (0) 2017.01.15
Go 튜토리얼 - 반복문, 제어문  (0) 2017.01.15
Go 튜토리얼 - 변수  (0) 2017.01.11
Comments