본문 바로가기

KOSA 클라우드 솔루션즈 아키텍트 양성과정

[5.17] Go 2일차

# 개념 #

 

* 타입 지정 상수와 타입 미지정 상수

  - 프로그래밍 의도

  - 타입 미지정 상수는 리터럴과 같은 취급

  - 타입 지정 상수는 해당 타입 변수에만 할당해야 함

 

* 사용하지 않는 변수

  - 지역 변수는 반드시 사용되어야 함

  - 사용되지 않는 상수는 허용

 

* 변수와 상수 이름 짓기

  - Go는 유니코드 문자를 식별자로 허용 ( 권장X )

 

* Go는 관용적으로 스네이크 표기법 사용하지 않음

  - 낙타 표기법, 파스칼 표기법 사용

 

* 상수 : 모든 문자를 대문자, 각 단어는 밑줄로 구분

  - Go는 이러한 일반 상수 이름 규칙을 따르지 않음

  - 패키지에 포함된 요소를 외부에 노출시킬지 (expose) 여부를 식별자의 첫 글자가 대소문자 여부로 결정

 

* 함수 내에서는 짧은 변수 이름 선호

  - 변수의 의미보다 간결성을 선호하는 Go

 

* int Score = 10

  String strName

 

* 짧은 이름

  - 코드 간결

  - 코드의 복잡도 판별 기준

 

* 패키지 블록 내

  - 설명적인 변수, 상수 이름 사용하기

 

* 배열(array)

  - 같은 타입의 여러 데이터를 담음

  - 시퀀스 타입 ( 순서 중요 )

  - Go에서는 선호하지 않음 ( 특별한 경우에만 사용 )

  - 선언 시 크기를 지정해야 함

 

* 선언 방법

  - 제로 값으로 선언 : 배열의 크기와 배열 내 요소 타입 지정

  - 배열 초깃값 지정 : 배열 리터럴 사용

  - 희소 배열 : 대부분의 요소가 0인 배열

  - 배열의 크기 지정하지 않았을 때 : 배열 리터럴 필요

  - 다차원 배열: [ ]의 개수가 차원 수

 

* 배열 요소 접근

  - [ ] 사용

 

* 배열 길이

  - len( ) 함수

 

* Go에서 배열을 잘 사용하지 않는 이유

  - 배열의 크기가 배열의 타입을 결정하는 데 사용되기 때문

  - 즉, 원소의 타입이 같은 배열이라도 크기가 다르면 다른 타입

  - 크기(길이)가 다르면 타입 변환도 불가능함 -> ex) 원소 개수가 3개인 int배열을 원소 개수 2개인 int배열로 변경X

 

* 슬라이스

  - 일련의 값(시퀀스)을 저장하는 자료 구조

  - 순서 중요

  - 슬라이스의 크기는 타입의 일부 아님 ( 배열은 배열의 크기가 타입의 일부인 것과 대비됨)

  - 슬라이스 간 비교는 불가 ( 배열과 다른 점 )

  - 단, 슬라이스도 nil과는 비교 가능 ( ==, != )

 

* 슬라이스 선언 (슬라이스 크기를 지정하지 않음)

  - 슬라이스 초기값 지정 : 슬라이스 리터럴

  - 희소 슬라이스

  - 다차원 슬라이스

  - 제로 슬라이스

    - 슬라이스의 제로 값은 nil

    - nil : 값의 부재 상태, 타입이 없음

  - 비어 있는 슬라이스 : 슬라이스를 슬라이스 리터럴 없이 선언만 하는 것

  - make( ) 함수 사용하여 생성 : 수용량 지정 가능

 

* 슬라이스의 길이

  - len( ) 함수 사용

 

* append

  - 슬라이스에 새로운 요소 추가

  - append의 결과를 할당하지 않으면 컴파일 애러 발생

 

* 수용력(capacity)

  - 예약된 (미리 준비된) 연속적인(consecutive) 메모리 공간의 크기

  - 길이와 수용력 

  - 수용력 >= 길이

  - 요소가 추가되면 길이는 커지고 결국 수용력과 같아짐

  -길이와 수용력이 같은 상태에서 요소가 추가되면 Go 런타임이 더 큰 수용력을 가지는 새로운 슬라이스를 할당, 원본 슬라이스의 값들은 새 슬라이스에 복사됨, 추가된 값은 새 슬라이스에 append 되고 이 새 슬라이스가 반환됨

  - 수용력이 1024 보다 작으면 2배 증가, 그렇지 않으면 25%씩 확장

  - cap( ) vs len( )

 

* make( )

  - 슬라이스에 저장될 요소 개수를 미리 알 수 있다면 make( )를 사용해 효율적인 슬라이스 작업 가능

  - make로 생성한 슬라이스에 append를 사용할 때 주의할 것

 

* 슬라이스 선언

  - var data [ ]int => nil

  - var data = [ ]int{ } => nil(X)

  - 슬라이스를 아래 방식 중 어떤 것으로 생성할지 정리해 봐야 함

    - 제로 슬라이스

    - 슬라이스 리터럴

    - make( )

 

* 슬라이스 연산자( : )

  - 슬라이스로부터 슬라이스 생성

  - 슬라이스 연산자를 사용하면 복사본을 만들지 않고 메모리를 공유함

  - 슬라이싱과 append를 함께 사용하면 혼란이 가중됨

  - 하위 슬라이스의 수용력 = 원본 슬라이스의 수용력 - 하위 슬라이스 시작 오프셋

 

* 하위 슬라이스와 append를 아무 생각 없이 사용하면 혼란이 가중됨

  - 의도치 않은 값 변경 발생

  - 완전한 슬라이스 표현식(full slice expression)으로 해결

 

* 완전한 슬라이스 표현식

  - 하위 슬라이스에 얼마나 많은 메모리를 공유할 것인지 지정

  - 슬라이스 연산 시 콜론을 한 번 더 사용하여 세 번째 인자에 원본 슬라이스에서 하위 슬라이스의 마지막 요소의 위치 지정

  - 슬라이스 연산의 세 번째 인자의 값을 두 번째 인자의 값과 같도록 설정

 

* 배열을 슬라이스로 변환

  - 배열에 슬라이스 연산 적용

  - 메모리 공유 문제 존재

 

* copy( ) 내장 함수

  - copy( ) 내장 함수

  - copy의 첫 번째 인자는 슬라이스이어야 함

 

* 문자열, 룬, 바이트

  - 문자열은 룬으로 이루어진 것은 아님

  - 문자열은 바이트의 시퀀스임

  - 문자열의 길이는 바이트 수와 같음

  - 문자열에 슬라이스 연산 사용 가능

    - 문자열은 수정 불가(immutable)이므로 슬라이스의 메모리 공유 문제가 없음

    - 유니코드로 구성되므로 슬라이스를 했을 때 문자가 깨질 우려

 

* 룬(rune)

  - 문자열은 바이트 슬라이스 또는 룬 슬라이스로 변환 가능

 

* 맵

  - 순서 없는 데이터 처리 유용

  - ( key, value ) Pair

  [SYNTAX]

    var 변수명 map[키타입]값타입

  - 값 : 어느 타입도 가능

  - 키 : 비교 가능한 타입만 가능 (맵, 슬라이스는 탈락)

 

* 생성

- nil 맵(제로 값 할당) : map의 제로 값은 nil

    - nil 맵은 길이 0

    - nil 맵의 값을 읽으면 맵 값이 되는 타입의 제로 값

    - nil 맵에 값을 쓰려고 하면 패닉 발생

  - 맵 리터럴 : 비어 있는 맵 생성

    - nil 맵과 다름

    - 길이는 0

    - 비어 있는 맵 리터럴이 할당된 맵을 읽고 쓸 수 있음

  - 값이 있는 맵 리터럴

    - 키와 값을 콜론으로 구분

    - 마지막 요소(키, 값)의 끝에 콤마(,)를 붙임

  - make( ) 함수로 생성

    - 맵의 요소 개수를 안다면

    - 길이는 0  (make( )로 슬라이스 만드는 것과 다름)

    - 초기 지정 개수 이상으로 커질 수 있음

    - 맵의 제로 값은 nil

    - 맵은 비교 불가능, 단 nil과 같은지 다른지는 비교 가능

 

* 맵 읽고 쓰기

  - := 연산자는 사용 불가

  - 아직 설정되지 않은 키에 할당된 값을 읽으면 값 타입의 제로 값이 반환됨

 

* 콤마 OK 관용구 (idiom)

  - 맵의 키에 대응되는 값이 없어도 제로 값이 리턴되지만

  - 맵에 키가 존재하는지 확인할 필요가 있을 때, 주로 사용하는 패턴

    - 맵에 키가 없어서 제로 값이 반환되는 건지

    - 실제로 키가 있는데 해당 값이 제로인 건지

 

* 맵 (요소) 삭제

  - delete( ) 내장 함수 사용

  - 키가 존재하지 않거나 nil 맵인 경우 아무것도 일어나지 않음

  - delete( ) 함수는 반환값이 없음

 

* 맵을 셋(집합)으로 이용

  - 집합(셋)

    - Uniqueness, 순서 없음

  - Go는 집합형을 직접 지원하지 않고 맵을 통해 간접적으로 지원

    - 집합의 원소로 쓰고 싶은 타입을 맵의 키 타입으로

    - 맵의 값을 불리언으로 설정

 

* 구조체

  - 여러 데이터 타입을 한데 묶어서 다루고 싶을 때 사용

  - struct 키워드, type 키워드

  - 구조체는 사용자 정의 타입

  - 따라서 바로 사용할 수는 없고

  - 구조체 정의 -> 구조체를 타입으로 하는 변수 선언

  - 구조체 항목들은 콤마로 구분하지 않음

  - 구조체는 어떤 블록 레벨에서도 정의 가능

  - 구조체의 제로 값

    - 구조체를 구성하는 항목들의 제로 값

  - 구조체 리터럴

   -첫 번째 방법

    - 구조체 항목 값은 구조체 정의한 순서대로 나열

    - 구조체 항목 값은 콤마로 구분하고 마지막 항목에도 콤마를 붙여야 함

   - 두 번째 방법

    - 맵 리터럴과 유사

    - 순서 무관

    - 생략할 경우 제로 값으로 설정

  - 위 두 개의 방법을 혼용할 수는 없음

  - 제로 구조체와 비어 있는 구조체는 차이점이 없음

  - 구조체의 멤버(항목)에 접근할 때는 인덱싱이 아니라 점 표기법을 사용

 

* 익명 구조체

  - 한 번만 사용할 구조체

  - type 생략 -> 구조체 이름이 없음

  - 구조체 변수만 존재

  - 주요 용도

    - 마샬링, 언마샬링

    - 테스트 작성

 

* 구조체 비교와 변환

  - 구조체 비교는 항목에 따라 다름

  - 두 개의 구조체가 같은 이름, 순서, 타입으로 구성되어 있으며 구조체 간에 타입 변환 가능


# 실습 #

리터럴

* var x [3]int : 3개의 원소를 가진 배열 선언

* var y = [3]int{10, 20, 30} : 배열 리터럴 -> 원소가 3개인 배열을 선언하고 원소로 10, 20, 30을 넣음

* fmt.Println([2]float32{2.1, 3.3}) : 원소 2개인 배열을 선언하고 원소로 2.1과 3.3을 넣음

 

원하는 위치에 넣기

* var z = [12]int{1, 2:5, 3, 10: 100, 101} : 2번째 원소에 5를 넣고 10번째 원소에 100을 넣음, 나머지는 순서대로

 

...

* ...을 사용해서 배열 초기화 시 배열의 개수를 명시하지 않을 수도 있음

 

배열의 길이를 비교

* x와 y 배열의 길이를 비교할 수 있음

 

다차원 배열

* 다차원 배열을 제로 값으로 초기화

* 원소 3개짜리 배열 2개를 포함하는 다차원 배열 : [[0,0,0] [0,0,0]]

 

배열에 원소 삽입

* 제로값으로 초기화된 다차원 배열의 첫 번째 배열의 첫번째 원소에 77 삽입 : [[77,0,0] [0,0,0]]

 

음수 인덱스는 허용하지 않음

* 음수 인덱스를 사용 시 컴파일에는 문제가 없지만 실행 시 runtime error : index out of range 발생

 

슬라이스

* 크기를 지정한 슬라이스와 크기를 지정하지 않은 슬라이스 같은 값 출력됨

 

제로 슬라이스와 비어 있는 슬라이스

* 제로 슬라이스 : 슬라이스 리터럴 없이 선언만 함

  - 슬라이스의 제로 값은 nil

  - nil : 값의 부재 ( absence of value ) 상태, 타입이 없음(어떤 요소도 포함하고 있지 않다는 의미)

* 비어있는 슬라이스 : 슬라이스 리터럴에 초깃값이 없음

 

append

* append로 x 배열에 y배열을 넣을 때 그냥 x = append(x, y)는 안 됨, y뒤에 ... 을 붙여 줘야 함 

 

수용력

* 수용력이 1,024보다 작은 경우에 수용력을 2배씩 확장하고 그 보다 큰 경우에는 25%씩 확장함

* 10과 20을 append 했을 때는 len( )과  cap( )의 값이 같았지만,

  30을 append 하는 순간 len( )은 3이 되고 cap( )은 2배가 늘어난 4가 됨

'KOSA 클라우드 솔루션즈 아키텍트 양성과정' 카테고리의 다른 글

[5.19] Go 4일차  (0) 2022.05.19
[5.18] Go 3일차  (0) 2022.05.18
[5.16] Go 1일차  (0) 2022.05.16
[5.13] Python 5일차  (0) 2022.05.13
[5.12] Python 4일차  (0) 2022.05.12