# 개념 #
* 타입 지정 상수와 타입 미지정 상수
- 프로그래밍 의도
- 타입 미지정 상수는 리터럴과 같은 취급
- 타입 지정 상수는 해당 타입 변수에만 할당해야 함
* 사용하지 않는 변수
- 지역 변수는 반드시 사용되어야 함
- 사용되지 않는 상수는 허용
* 변수와 상수 이름 짓기
- 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로 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 |