본문 바로가기

Go

Array & Slice

[1. 배열]

  • Go 에서 배열은 Slice 와 달리 고정된 크기의 길이를 갖는다.
  • 또한, 같은 자료형을 저장 할 지라도 이 길이가 다르면 서로 다른 자료형으로 처리한다.
  • 아래 코드에서 주석을 해제하면 실행과 빌드 모두 되지 않는다.

 

[2. Slice]

  • 배열을 기초로 하지만, 그 크기를 동적으로 관리 할 수 있다.
  • 또한, 부분 Slice 가 가능하다.
  • 실제로, 배열과 비슷하게 선언을 하지만, 그 길이를 따로 명시하지 않는다. 

 

[3. 예제]

package main

import "fmt"

func slice_test(sl []int) {
	if len(sl) > 0 {
		sl[0] = 9
	}
	fmt.Printf("%p ", &sl)
	fmt.Println(sl)
}

func array_test(arr [5]int) {
	//arr = append(arr, 7)
	arr[0] = 7
	fmt.Printf("%p ", &arr)
	fmt.Println(arr)
}

func array_test1(arr [7]int) {
	arr[0] = 9
	fmt.Println(arr)
}

func main() {
	var sl1 []int
	sl2 := []int{}
	sl3 := make([]int, 0, 5)
	sl4 := make([]int, 5, 20)

	slice_test(sl1)
	fmt.Printf("%p ", &sl1)
	fmt.Println(sl1)

	slice_test(sl2)
	fmt.Printf("%p ", &sl2)
	fmt.Println(sl2)

	slice_test(sl3)
	fmt.Printf("%p ", &sl3)
	fmt.Println(sl3)

	slice_test(sl4)
	fmt.Printf("%p ", &sl4)
	fmt.Println(sl4)

	fmt.Println("==========")

	var ar1 [5]int
	ar2 := [5]int{}

	array_test(ar1)
	fmt.Printf("%p ", &ar1)
	fmt.Println(ar1)

	array_test(ar2)
	fmt.Printf("%p ", &ar2)
	fmt.Println(ar2)

	//array_test1(ar2)
}

 

[4. 출력 및 해석]

배열과 달리 Slice를 Pass by value 형태로 넘겼을 때 출력이 다르다.

특히, 7번 8번 라인에서 Slice의 주소가 다른데 내부 데이터는 같다는 것을 볼 수 있다.

 

이는 Slice 를 관리하는 구조에 대한 차이이다.

C 관점에서 보면 Slice 의 데이터 구조는 아래와 같다.

  • T *ptr
  • int length;
  • int capacity

즉, Slice를 Pass by value 로 넘겼을 때 내부 자료구조를 그대로 복사하기 때문에,

Slice 내 내부 배열을 참조하게 되는 것이다.

따라서 변경 된 사항이 원래 Slice 에도 반영 된 것이고,

 

배열은 그 자체가 하나의 자료형이라 볼 수 있으므로,

Pass by value 로 넘겼을 때 원래 데이터를 참조하지 않기 때문에, 내부 값이 변경되지 않은 것이다.

 

'Go' 카테고리의 다른 글

GO111MODULE  (0) 2022.08.10
go 패키지 설치, 관리  (0) 2022.08.10
ubuntu go version update  (0) 2022.04.06
cgo  (0) 2022.03.19
Slice length, capacity and append, copy function  (0) 2022.02.08