[The Go Programming Language] 2장 프로그램 구조 - 2.5 타입 선언

in #kr-dev6 years ago (edited)

modolee_logo
안녕하세요. 개발자 모도리입니다.
The Go Programming Language 라는 책으로 Go를 공부하고 있으며, 해당 책의 내용을 요약 정리해서 올리려고 합니다. 저는 번역본을 구매해서 공부하고 있습니다.
예제코드 라고 나오는 것들은 https://github.com/modolee/tgpl.git 에서 다운 받으실 수 있습니다.

지난 게시물


2장 프로그램 구조

2.5 타입 선언

변수의 사용

  • 변수나 표현식의 타입은 크기, 내부 표현 방식, 수행 가능한 고유 작업, 연관된 메소드와 같은 해당 값의 특성을 정의합니다.
  • 모든 프로그램에는 동일하게 표현하지만, 매우 다른 개념의 가진 변수가 있습니다.
    • int : 루프 인덱스, 타임스탬프, 파일 디스크립터, 개월 수
    • float64 : 길이(m), 속도(m/s), 온도
    • string : 암호, 색상의 이름

새로운 명명된 타입

  • 타입 선언은 기존 타입과 같은 내부 타입을 갖는 새 명명된 타입을 정의합니다.
  • 명명된 타입은 별개의 호환되지 않을 수도 있는 내부 타입에 이름을 붙여 의도치 않게 섞이지 않도록 합니다.
    type 이름 내부타입
  • 타입 선언은 명명된 타입을 패키지 전체에서 볼 수 있는 패키지 수준에서 가장 많이 나타나며, 이름이 export되면(대문자로 시작할 때) 다른 패키지에서도 볼 수 있습니다.

섭씨, 화씨 온도 타입 선언

  • 이 패키지는 온도의 두 가지 단위에 Celsius(섭씨), Fahrenheit(화씨)의 두 타입을 정의합니다.
  • 둘 다 동일한 내부 타입인 float64를 사용하지만 동일한 타입이 아니기 때문에 산술식으로 비교하거나 결합할 수 없습니다. 이 덕분에 무심코 서로 다른 단위의 온도를 조합하는 오류를 방지할 수 있습니다.
package tempconv0

import "fmt"

type Celsius float64
type Fahrenheit float64

const (
    AbsoluteZeroC Celsius = -273.15
    FreezingC     Celsius = 0
    BoilingC      Celsius = 100
)

func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) }

func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) }

func (c Celsius) String() string { return fmt.Sprintf("%gºC", c) }

예제코드 [ch2/tempconv0/tempconv0.go]

사용 예제

  • Example1 - 산술 연산자
    • 명명된 타입의 내부 타입이 구조와 표현 및 지원되는 고유의 작업을 결정하며, 이는 내부 타입을 직접 사용할 때와 마찬가지입니다.
    • 즉, 산술 연산자는 예상했듯이 Celsius와 Fahrenheit에서 float64와 동일하게 동작합니다.
  • Example2 - 비교 연산자
    • 명명된 타입과 동일한 타입이나 동일한 내부 타입을 가진 이름 없는 타입의 값은 ==< 같은 비교 연산자로 비교할 수 있습니다.
  • Example3 - 메소드 정의
    • 예제코드 [ch2/tempconv0/tempconv0.go]의 마지막 줄에 해당하는 내용입니다.
    • Celsius 파라미터 c를 함수명 앞에 표기했으며, c의 숫자 값에 ºC를 붙여 반환하는 String 메소드를 Celsius 타입에 연결합니다.
    • 많은 타입이 이런 형태의 String 메소드를 정의해 해당 타입 값이 fmt 패키지에 의해 문자열로 출력 될 때의 출력 형태를 제어합니다.
package tempconv0

import "fmt"

func Example1() {
    fmt.Printf("%g\n", BoilingC-FreezingC) // "100"
    boilingF := CToF(BoilingC)
    fmt.Printf("%g\n", boilingF-CToF(FreezingC)) // "180"
    //fmt.Printf("%g\n", boilingF-tempconv0.FreezingC) // 컴파일 오류 : 타입 불일치
}

func Example2() {
    var c Celsius
    var f Fahrenheit
    fmt.Println(c == 0) // "true"
    fmt.Println(f >= 0) // "true"
    //fmt.Println(c == f) // 컴파일 오류 : 타입 불일치
    fmt.Println(c == Celsius(f)) // "true"!
}

func Example3() {
    c := FToC(212.0)
    fmt.Println(c.String()) // "100ºC"
    fmt.Printf("%v\n", c)   // "100ºC"
    fmt.Printf("%s\n", c)   // "100ºC"
    fmt.Println(c)          // "100ºC"
    fmt.Printf("%g\n", c)   // "100"; String을 호출하지 않음
    fmt.Println(float64(c)) // "100"; String을 호출하지 않음
}

예제코드 [ch2/tempconv0/examples.go]

패키지 사용을 위한 위치 지정
위의 예제코드들은 패키지로 만들어져 있어서 실제 실행을 위해서는 main 패키지를 만들어서 실행해야 합니다.
패키지의 위치는 GOPATH로 지정한 경로의 src 폴더가 루트 경로가 됩니다.
저는 ~/Dev/go/ 를 GOPATH로 지정했습니다.
그래서 package 파일들은 ~/Dev/go/src/ 밑에 저장하고 있으며 tgpl/ch2/tempconv0 형태로 폴더를 만들고 패키지 폴더를 만들어서 폴더 별로 패키지를 저장합니다.
그냥 테스트 실행을 위한 파일들은 아래 예제코드와 같이 ch2/루트에 위치해 했습니다.

package main

import (
    "fmt"
    "tgpl/ch2/tempconv0"
)

func main() {
    fmt.Println("<<-- Example1 -->>")
    tempconv0.Example1()
    fmt.Println("<<-- Example2 -->>")
    tempconv0.Example2()
    fmt.Println("<<-- Example3 -->>")
    tempconv0.Example3()
}

예제코드 [ch2/tempconv0_main.go]

실행결과
$ go run ch2/tempconv0_main.go
<<-- Example1 -->>
100
180
<<-- Example2 -->>
true
true
true
<<-- Example3 -->>
100ºC
100ºC
100ºC
100ºC
100
100


이어보기

[The Go Programming Language] 2장 프로그램 구조 - 2.6 패키지와 파일

Sort:  

@modolee, I gave you a vote!
If you follow me, I will also follow you in return!