티스토리 뷰

Go

array와 slice

LichKing 2019. 3. 2. 16:19

go에는 array와 slice 라는 타입이있다. 이게 좀 묘한데 둘이거의같다.


func main() {
arr := [3]int{1, 2, 3}
slice := []int{1, 2, 3}

fmt.Println(arr)
fmt.Println(slice)
}


[3] 이라고 명시적으로 크기를 지정한건 배열, []로 선언한건 슬라이스다. 사용법도 비슷한데 슬라이스는 크기가 변경되는 반면 배열은 불가능하다. 이외에도 전반적으로 슬라이스가 배열의 superset 느낌이라.. 배열은 거의 사용할일이 없을듯하다. 그리고 한가지 치명적(?)인 차이가 슬라이스는 함수의 인자로 전달할때 레퍼런스가 전달되는반면 배열은 복사본이 전달된다는 점이다.


func main() {
slice := []int{3, 1, 2}
arr := [3]int{3, 1, 2}

testArr(arr)
testSlice(slice)

fmt.Println(arr)
fmt.Println(slice)
}

func testArr(arr [3]int) {
arr[0] = 100
}

func testSlice(slice []int) {
slice[0] = 100
}


자꾸 자바랑 비교하면 안되는데;; 슬라이스는 ArrayList 느낌이고, 배열은 그냥 배열이라고 생각하면 이해하는데 좀 도움이 되지 않을까싶다.


slice도 (자바의) ArrayList랑 똑같이 용량(capacity)와 길이(size, len)가 구분되어 존재하며 둘은 다를 수 있다. capacity를 초과하게되면 내부적으로 2배를 늘리게된다.


func main() {
slice := []int{1, 2, 3}

fmt.Println(len(slice))
fmt.Println(cap(slice))

slice = append(slice, 4)

fmt.Println(len(slice))
fmt.Println(cap(slice))
}


이 코드를 실행해서 출력문을 보게되면 capacity와 len의 차이를 알게될것이다. 요소를 추가하는 append() 함수의 경우 배열은 인자로 받지않고, 슬라이스만 넣을 수 있다.


배열이나 슬라이스의 일부분을 복사할때는 : 연산자를 사용하면된다.


func main() {
slice := []int{1, 2, 3}

copySlice := slice[1:2]

fmt.Println(copySlice)
}


첫번째 인덱스는 포함하고 두번째 인덱스는 포함하지 않는다. 즉 예제 코드의 경우 1 인덱스의 값만 지닌 1개짜리 슬라이스를 리턴한다.


위에서 잠깐 잘못설명한게 있는데 : 연산자는 슬라이스(혹은 배열)의 '복사본' 을 만드는게 아니고 그 참조만 가지고온다. 그래서 : 연산자의 결과로 나온 슬라이스를 수정하면 원본 슬라이스도 함께 수정된다.


func main() {
slice := []int{1, 2, 3}

copySlice := slice[1:2]
copySlice[0] = 10

fmt.Println(slice)
}


정말 '복사'를 하려면 기본적으로 지원되는 copy() 함수를 이용하면 된다.


func main() {
slice := []int{1, 2, 3}
copySlice := make([]int, 3)

copy(copySlice, slice)

copySlice[0] = 10

fmt.Println(slice)
fmt.Println(copySlice)
}


설명한적없는 make() 라는 함수를 사용했는데, 초기화없이 빈 슬라이스를 사용할땐 예제 코드와같이 make() 함수를 이용해서 만들수 있다.


슬라이스를 정렬할때는 sort 패키지를 사용하면된다.


func main() {
slice := []int{3, 1, 2}

sort.Ints(slice)

fmt.Println(slice)
}


int 같은 기본타입을 지원하는 함수가 있을땐 사용하면되고, 자바에서 Comparator를 이용하는것처럼 정렬 함수를 전달해서 정렬할 수 도 있다.


func main() {
slice := []int{3, 1, 2}

sort.Slice(slice, func(i, j int) bool {
return slice[i] < slice[j]
})

fmt.Println(slice)
}


배열은 처음 말한것처럼 복사본을 전달하기때문에 상태변경을 할수 없어서 그런지 배열은 따로 지원하지않는다.

'Go' 카테고리의 다른 글

goroutine  (0) 2019.03.28
command line argument 받기  (0) 2019.03.23
array와 slice  (0) 2019.03.02
panic() 과 recover()  (0) 2019.03.01
defer 키워드  (0) 2019.03.01
댓글
댓글쓰기 폼