array
프로그래밍 언어에서 array라 하면 보통 정적 배열(static array)을 의미한다. 정적 배열은 배열 자체로 확장 또는 축소가 안된다. 정적 배열의 반대는 동적 배열인데 동적 배열은 정적 배열과 같지만 대부분의 프로그래밍 언어는 동적 배열을 API [Application Programming Interface]로 지원하기 때문에 개발자가 직접 배열을 확장하거나 축소하는 코드를 작성하지 않고 사용할 수 있다. Java는 ArrayList라는 Class를 API로 지원하고 Go는 slice라는 API로 지원한다. (slice라는 타입이 있는 게 아니고 array선언 방식과 내장 API을 사용하는 거다.) 오늘은 array를 기준으로 포스트 할 예정이고 slice를 포스트 할 때 array의 일부 내용을 보강하는 형식으로 하겠다.
- 명시적 선언
Go는 신기하게 타입을 명시하는 부분에 [5]int와 같이 배열의 크기를 명시해야 한다. 보통 Java나 다른 프로그래밍 언어에서는 int[] arr = new int [5]{....} 이런 식으로 타입 부분이 아닌 초기화 영역에서 배열의 크기를 명시하는 방식으로 코딩하는데 Go에서는 타입을 명시하는 곳에 배열의 크기를 꼭 명시해야 줘야 한다.
책에서는 [5]int가 타입 그 자체라고 설명하며 웃긴 건 앞에 [5]int라고 명시했으면 초기화하는 곳도 마찬가지로 [5]int 여야 한다. 다른 방법으로는 초기화 영역의 요소 타입을 명시하는 부분에 [...]int 이런 방법도 있다.
주의할 점이 있는데 array type에 [...]int와 같이 (...)을 사용할 수 없고 초기화 영역에서 요소의 타입을 [...]int 이렇게 명시해도 array type에 명시한 배열의 크기만큼 요소를 초기화하지 않으면 에러가 뿜! 뿜! 한다.
이렇게 복잡한고 외우기 힘든 선언 방식보다 조금 더 쉽게 명시적 선언할 수 있다.
위와 같이 배열 변수의 크기만 명시하고 선언할 수 있는데 이땐 해당 배열의 타입의 기본값(int = 0, float64 = 0.0, bool = false, string = "" 등등등)으로 초기화된다. 이 방법은 사용할 일이 거의 없을 것 같은데 그 이유는 해당 배열 변수를 대입하기 위해 반복문을 돌려야 하기 때문이다. 반복문을 사용한다 해도 배열의 크기를 확인해야 하고 정적 배열의 이점은 별로 없는 것 같다. 다른 방법으론 명시적 선언에서 가장 쉽고 실무에서도 쓸법한??? 방법도 있다.
위와 같은 방법이 가장 많이 사용될 것 같다. 유심 깊게 봐야 하는 부분은 c변수와 f변수인데 c변수의 배열 크기는 5이지만 초기화 요소는 세 개뿐이다. 이땐 부족한 개수만큼 배열 타입의 기본 값으로 초기화된다. f변수를 보면 [...]int로 크기를 명시했는데 이건 초기화 요소의 개수만큼 배열의 크기가 지정된다. 참고로 [...]int는 array type이 아니라고 한다. (그럼 array type이 아니고 뭐야... 책에는 설명이 없는데....) - 묵시적 선언
Go에서는 변수 선언 시 묵시적 선언을 권장한다. 그 이유는 명시적 선언보다 훨씬 간결한 코드를 만들 수 있는 이유인 것 같다. 명시적 선언보다 묵시적 선언이 엄청 쉽고 정적 배열을 사용해야 한다면 이 방법을 사용할 것 같다.
사실 위 사진 중 array가 아닌 스파이가 숨어있다. g변수와 j변수인데 Go는 배열 변수 선언 시 대괄호 안에 배열을 크기를 명시하지 않으면 array가 아닌 slice다.
주의할 점은 j변수처럼 요소를 초기화도 안 하고 index로 배열에 접근할 때 예외가 발생한다. 개발하다 실수하기 딱 좋을 것 같은데 그 이유는 j 배열 변수에 index로 접근 시 컴파일 시점에 에러를 표출하는 것이 아닌 실행 시점에 예외를 발생한다는 점 때문이다.
물론 내장 API를 사용하면 문제없이 사용할 수 있지만 그 내용은 slice를 포스트 할 때 하겠다.
지금 까지 정적 배열 변수를 선언하는 방법을 알아봤다. 지금부턴 어떻게 보면 기본적인 내용이지만 array 사용 시 주의점을 알아보겠다.
- 배열 선언 시 기본 타입이 표현할 수 있는 범위보다 높은 값을 초기화 및 대입 시 에러
- 배열의 크기가 같더라도 기본 타입이 다를 때 대입 시 에러
- 배열 대입 시 얕은 복사(Shallow Copy)다.
어떻게 보면 array와 slice의 가장 큰 차이점이라 할 수 있을 것 같다. x라는 변수를 z라는 변수에 선언과 동시에 초기화 시 x변수가 가리키고 있는 메모리 주소를 z라는 변수도 가리키게 하는 것이 아닌 x변수의 메모리 크기만큼 새로운 메모리를 생성 후 z라는 변수가 가리키게 한다. 쉽게 이야기하면 x변수가 사용하고 있는 메모리만큼 더 사용한다는 것이다.
array를 더 이야기하려면 반복문이나 slice의 내용을 포함해야 해서 너무 지루할 것 같아 여기서 마무리하겠다.
다음 포스트 할 내용은 interface와 nil이다. (책 순서대로다... ㅎㅎ) 부족하거나 미흡한 내용이 있다면 알려주시기 부탁드립니다. 그럼 ㅃ2~
'Golang > Study' 카테고리의 다른 글
chapter3(9) method - signature (0) | 2022.02.11 |
---|---|
chapter3(8) primitive type - interface{} and nil (0) | 2022.02.06 |
chapter3(6) primitive type - rune and string (0) | 2022.02.01 |
chapter3(5) primitive type - float and complex (0) | 2022.02.01 |
chapter3(4) primitive type - wrap around (0) | 2022.01.30 |