본문 바로가기

Go/[Go]배열, 슬라이스, 맵

슬라이스

Go의 슬라이스는 값을 추가하여 확장할 수 있는 데이터 구조입니다.

배열과 동일하게 슬라이스는 동일한 Type을 가지는 값들로 구성되어 있습니다.

이때, 슬라이스는 배열과는 다르게 끝부분에 값을 추가할 수 있는 함수를 가지고 있다는 것입니다.

 

슬라이스 변수 선언 방법

var devhsops1 [5]int
var devhsops2 []int
  • devhsops1은 배열과 동일하게 크기를 지정하여 변수를 선언하는 방법입니다.
  • devhsops2는 크기를 지정하지 않고 변수를 선언하는 방법입니다.

크기를 지정하지 않고 변수를 선언하는 경우엔, 슬라이스는 배열과는 다르게 크기를 동적으로 지정해야합니다.

devhsops2 = make([]int, 5)

단축 변수 선언과 함께 사용하게 되면 더욱 간단하게 코드로 구현할 수 있습니다.

devhsops3 := make([]int, 5)

앞전에 "배열 리터럴"에 대해 설명하였습니다.

https://devhsops.tistory.com/14

 

배열

배열이란 무엇일까요? 배열이란, 연관된 데이터를 그룹핑하여 관리하기 위해 사용되는 데이터 타입입니다. 또한, 배열은 동일한 타입을 갖는 값의 모음으로, 데이터를 효율적으로 관리 및 이용

devhsops.tistory.com

슬라이스 값을 초기화 하기위해서는 "슬라이스 리터럴"을 사용하면 해결할 수 있습니다. 이때, 슬라이스 리터럴은 배열 리터럴과는 다르게 빈 대괄호로 나타내어 슬라이스 값들을 초기화할 수 있습니다.

devhsops4 := []int{1,2,3,4,5}

 

슬라이스 연산자

 

슬라이스는 일부 배열의 원소 또는 전체에 대한 추상화된 뷰입니다.

 

이를 기반으로, 슬라이스 연산자를 사용하게 되면 해당 슬라이스를 기반으로 하는 새로운 슬라이스를 만들 수 있다는 사실을 알 수 있는데요. 이해를 위해 예시를 들어 설명하겠습니다.

devhsops1 := []int{1,2,3,4,5}
devhsops2 := devhsops1[1:3] // index => 1이상 3미만
devhsops3 := devhsops1[1:] // index => 1이상 마지막 원소까지
devhsops4 := devhsops1[:3] // index => 처음부터 3미만 원소까지
  • devhsops2의 값은 [2, 3]라는 원소를 가지게 될 것입니다.
  • devhsops3의 값은 [2,3,4,5]라는 원소를 가지게 될 것입니다.
  • devhsops4의 값은 [1,2,3]라는 원소를 가지게 될 것입니다.

이처럼 슬라이스는 자체적으로 데이터를 저장하지 않고, 실제 데이터가 저장되는 배열에 대한 "뷰"라는 것입니다.

 

따라서, 해당 예시에서 devhsops2, devhsops3, devhsops4의 값을 수정하게 되면, 실제 뷰가 저장되어 있는 공간인 devhsops1의 값이 함께 수정된다는 사실을 알 수 있습니다. 반대로, devhsops1을 수정하게 되면 이것의 뷰를 공유하는 다른 슬라이스들의 값 또한 함께 수정될 것입니다.

 

이러한 문제를 방지하기 위해 슬라이스 연산자를 사용하는 것보다 make 또는 슬라이스 리터럴을 사용하여 슬라이스를 만드는 것이 더욱 안전합니다.

 

슬라이스는 값을 추가하여 확장할 수 있는 데이터 구조(append)

 

이제부터 슬라이스에 값을 추가하여 확장하는 방법에 대하여 설명을 이어나나겠습니다.

 

Go의 내장 함수 중 append라는 것이 있습니다.

 

append는 (슬라이스 + 추가할 값...)을 인자로 받아 새로운 슬라이스를 반환합니다.

이처럼 append는 기존 슬라이스 변수에 재할당하는 기능을 수행하는데, 슬라이싱 연산자에서 발생할 수 있는 문제를 야기할 수도 있다는 문제가 있습니다.

 

예를 들어 설명하겠습니다.

devhsops1 := []int{1,2,3} // 1,2,3
devhsops2 := append(devhsops1, 4, 5) // 1,2,3,4,5
devhsops2[0] = 100
// devhsops1 => 100, 2, 3
// devhsops2 => 100, 2, 3, 4, 5

이와 같은 문제가 발생할 수 있습니다. 따라서, append를 사용할 때엔 append에 전달한 슬라이스 변수와 동일한 슬라이스의 변수에 재할당하는 것이 일관성 문제를 해결할 수 있습니다.

 

+a

가변 인자 함수

 

fmt.Println() 또는 append()에 입력되는 인자값들을 생각해보면 갯수가 정해지지 않은 가변 인자 함수라는 것을 알 수 있습니다. 이와 같이 가변 인자 함수를 구현하는 어떠한 방법들이 있는지에 대하여 설명드리겠습니다.

 

즉, 가변 인자 함수란? 정해지지 않은 개수의 인자를 가지고 사용할 수 있는 함수입니다.

 

코드로 예시를 보여드리겠습니다.

func myDev(devhsops ...int){
    for _, number := range devhsops{
        fmt.Println(number)
    }
}

func main(){
    devhsops1 := []int{1,2,3,4,5}
    
    // 정상 동작하는 코드
    myDev(1,2,3,4,5) 
    myDev(3,4) 
    myDev()
    myDev(devhsops1...)
    myDev(inRange(1,10, 2,4,6, 11, -1)) // 1~10사이의 값들을 반환합니다.
    
    // 비정상 코드
    myDev(devhsops1)
}

이처럼 가변 인자 함수를 나타내는 "..."으로 임의 개수를 가지는 인자값을 함수로 전달할 수 있습니다.

'Go > [Go]배열, 슬라이스, 맵' 카테고리의 다른 글

  (0) 2021.11.22
텍스트 파일 읽기  (0) 2021.11.22
배열  (0) 2021.11.22