본문 바로가기

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

[5.19] Go 4일차

# 개념 #

 

* defer

  - 정리 작업을 수행하는 함수 지정

  - 현재 코드 블록이 끝날 때 자동으로 실행

  - defer는 여러 번 사용될 수 있음 -> 나중에 defer 된 함수가 먼저 실행됨(LIFO)

  - defer가 적용된 함수 중 반환 값이 있는 함수의 반환 값은 따로 읽을 수 없음

  - defer와 이름 지정된 반환 값

 

* 값에 의한 호출(Call by Value)을 사용하는 Go

  - Call by Value : 인자나 반환 값이 복사됨

    - 원본이 변경되지 않음

    - 데이터 보호 측면에서 유용

    - 대량의 데이터를 처리할 경우 메모리와 시간이 많이 필요

  cf.) Call by Reference : 주소가 복사됨

        - 대용량 데이터의 전송이나 수정 시 주소만 넘겨주면 원본을 수정할 수 있어 복사가 필요 없음

        - 원본이 변경될 우려 존재

  - 기본 타입, 구조체는 call by value

  - 맵

    - 파라미터로 넘어온 맵에 대한 변경은 원본에도 적용

  - 슬라이스

    - 길이 조정 외의 모든 조작이 원본에도 적용

  - 맵과 슬라이스는 포인터로 구현이 되었기 때문에 원본도 변경되는 것

 

* 포인터

  - 값이 저장된 메모리의 위치 값(주소)을 저장하는 변수

  - 주소 연산자(&)

  - 간접 연산자(*, dereferencing operator)

  - int32는 4바이트

  - bool은 1바이트

  - 모든 포인터는 어떤 타입을 가리키는가에 무관하게 항상 같은 크기

  - 포인터의 제로 값 : nil

    - 슬라이스, 맵, 함수, 채널, 인터페이스의 제로 값 : nil

  - nil은 숫자 0이 아님

    - nil을 숫자로 변경/변환하거나 숫자를 반대로 변환할 수는 없음

  - 포인터  dereferencing 전에 nil인지 확인할 필요 있음

  - 포인터 타입

    - 포인터가 가리키는 값의 타입

    - 포인터가 어떤 타입의 값을 가리키는지 나타냄

    - 포인터 변수를 선언할 때 주로 사용

    - 타입 이름 앞에 *

    - cf.) 포인터 역참조 : 변수 이름 앞에 * (변수 이름 앞에 *는 포인터 역참조)

      - var pointerToX *int -> pointerToX라는 변수는 int포인터 타입 (타입 이름 앞에 *는 포인터 타입)

      - pointerToX = &x -> x는 int를 가리키는 변수인데 이 변수의 주소를 구해서 poiterToX에 저장함

    - 내장 함수 new( )

      - 포인터 변수 생성

      - 해당 타입의 제로 값을 가리키는 포인터 반환

  - 기본 타입의 리터럴이나 상수는 주소가 없으므로 주소 연산자를 사용할 수 없음

    - 헬퍼 함수를 사용하여 주소 연산자를 사용할 수 없는 문제 해결

  - 포인터는 변경 가능한 파라미터를 가리킴

 

* Java의 데이터 타입

  - 원시 타입(Primitive Type) : 8개

    - byte, short, int, long, float, double, bool, char : 값 그 자체, 객체가 아님, call by value

  - 클래스 : 객체를 참조 변수로 참조해서 작업, call by reference

    - 원시 타입의 클래스 : Byte, Short, Integer, Long, Float, Double, Boolean, Character

 

* Go 변수를 1) call by value로 할지 2) call by reference로 할지 선택 가능

  - 1) 함수에 변수를 그냥 넘기는 것

  - 2) 함수에 변수의 포인터를 넘기는 것

 

* 포인터는 변경 가능한 파라미터를 가리킴

  - 비 포인터 타입 : 기본 타입, 배열, 구조체 => 원본의 불변성

  - 포인터 : 함수로 전달되면 포인터의 복사본이 생성

    - 원본에 닿을 수 있음

    - 수정할 수 있음

 

* 포인터는 최후의 수단

  - 포인터

    - 데이터 흐름 이해를 어렵게 함

    - GC에게 추가 작업 부하를 걸게 됨 (포인터를 이용하면 주로 힙을 이용)

      : 가비지는 힙에 생성

    - 포인터는 모든 데이터 타입을 함수로 전달할 때 상수 시간이 걸림 O(n)

      - 주소를 함수에 전달하므로, 모든 데이터 타입의 주소 길이는 같음

    - 대략 1메가 바이트 전달 기준으로

      - 이상이면 포인터 전달

      - 이하면 값 전달

 

* 제로 값과 값없음의 차이

  - 0, ' '   vs   NULL(nil), ''

   값있음 vs   값없음

 

* 포인터를 이용하여 변수나 구조체 항목의 값이 제로 값인지 없는 값인지 구분

  - 할당되지 않은 변수나 구조체 항목에 nil 포인터를 사용

  - 포인터는 변경 가능함을 나타내므로 함수에서 nil 포인터를 직접 반환하는 것보다 콤마 OK 관용구를 사용하자

 

* nil 포인터를 함수의 파라미터나 구조체 항목의 값으로 담아서 함수의 인자로 넘기면 nil 포인터를 통해서는 값을 저장할 수 없으므로 함수 안에서 값을 설정(간접 연산자 *를 사용하는 것)할 수가 없음

 

* 버퍼 슬라이스

  - 메모리 용도에 따른 구분

    - 버퍼(buffer)

    - 캐시(cache)

    - 풀(pool)

 

* 가비지 컬렉션 작업량 줄이기

  - 버퍼를 이용하면  GC의 부하를 줄일 수 있음

  - 자동으로 메모리를 회수해 줌

  - 가비지(Garbage)

    - 더 이상 어떤 포인터도 가리키지 않는 데이터

 

* Go의 타입

  - 내장 타입

    - 기본 타입, 복합 타입

  - 구조체를 이용한 사용자 정의 타입

  - 구체적인 타입(구체 타입, concrete type)

    cf.) abstract type

        : abstract = general, super, 미완성(상속)

        <-> concrete = specific, sub, 완성(상속)

 

* 매서드

  - 타입(type)을 위한 메서드

    - 반드시 패키지 블록 레벨에서 정의해야 함

  - 리시버(receiver)

    - func 키워드와 메서드 이름 사이에 리시버_이름 타입을 괄호로 감싸서 정의

    - 리시버 식별자는 관례적으로 타입 이름의 짧은 약어인 첫 문자를 사용

 

* 포인터 리시버와 값 리시버

  - 결정하는 규칙

    - 메서드가 리시버를 수정 => 반드시 포인터 리시버 사용

    - 메서드가 nil 인스턴스를 처리할 필요 => 반드시 포인터 리시버 사용

    - 메서드가 리시버를 수정하지 않음 => 값 리시버 사용 가능

      - 타입에 선언된 다른 메서드에 따라 결정

      - 같은 타입의 다른 리시버가 포인터 리시버? : 리시버를 수정하지 않는 메서드라도 일관성을 위해 포인터 리시버 사용

 


# 실습 #

 

포인터의 제로 값

* int 타입을 가리키는 포인터 변수 x

* 포인터의 제로 값은 nil이므로 true 출력됨

 

x와 y의 타입

* 둘 다 int타입 출력

 

x와 y의 타입은 같지만..

* 내장 함수 new는 포인터 타입의 변수를 생성함 -> y라는 포인터 타입의 변수 생성

* 포인터 타입의 변수에 *를 붙이는 dereferencing(역참조)는 포인터 타입의 변수 y가 가리키는 값 0을 반환함

* fmt.Println(x) 하면 nil이 출력됨, fmt.Println(y)하면 주소 값이 출력됨

* 주어진 타입인 int의 제로 값을 가리키는 포인터 변수 y

* 포인터의 제로 값은 nil이지만 int 타입의 제로 값은 0

* 따라서, y == nil의 결과 false가 출력됨

 

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

[5.23] 오픈스택 총정리(설치, 설정 등)  (0) 2022.05.23
[5.20] Go 5일차(복습)  (0) 2022.05.20
[5.18] Go 3일차  (0) 2022.05.18
[5.17] Go 2일차  (0) 2022.05.17
[5.16] Go 1일차  (0) 2022.05.16