Skip to content

Latest commit

 

History

History
203 lines (151 loc) · 10.7 KB

2.02.md

File metadata and controls

203 lines (151 loc) · 10.7 KB

2.02 Hello World

Go 프로그램이 어떻게 작동하는지 알아보도록 하자. Go Playground를 사용하여 이 부분을 학습해 볼 것이다.
여러분들의 Go 프로그램안에 main 패키지를 필요로 한다. main 패키지 내에는, func main을 가지고 있어야 할 것이며, function main이 여러분들이 작성한 프로그램을 실행하는 곳이다. main 함수는 다양한 일을 수행할 수 있는데, 이는 여러분들의 프로그램의 시작점(entrypoint)이자 종료점(exitpoint)이기도 하다. 그렇기 때문에, func main() 영역을 벗어나면, 프로그램이 종료된다.

package main

import (
  "fmt"
)

func main() {
  fmt.Println("Hello, playground")
}

그러므로, 우리는 코드를 작성할 때, package main를 필요로 하며, 여기서package는 Golang의 키워드(keyword)이기도 하다. 어뗗게 우리는 packagekeyword인지 알 수 있을 것인가? 키워드에 대한 정의는 Golang Spec에서 확인 할 수 있다. Language Specificaition페이지로 이동한 다음, Keywords](https://golang.org/ref/spec#Keywords)의 리스트를 볼 수 있는 Lexical Elements를 확인하여 보도록 하자. 키워드가 그렇게 많지는 않으니 아래의 키워드를 참고하여 보자.

break        default      func         interface    select
case         defer        go           map          struct
chan         else         goto         package      switch
const        fallthrough  if           range        type
continue     for          import       return       var

여기서 우리는 package, import, func 등을 확인할 수 있다.

그래서, 다시 정리해 보면, 우리는 코드를 작성할 때, 패키지 선언(package declaration)을 하여야 한다. 위와 같은 경우, package main이 패키지 선언부분이다. 우리는 스탠다드 Go 라이브러리로부터 "fmt" 패키지를 import 하여 위의 프로그램의 일부로서 포함하고 있으며, 이를 func main()내에서 사용하고 있다. 예를들면, fmt 패키지로부터 Println 함수를 가져와서 main 함수에서 호출하고 있다.

우리는 종종 다른 패키지들을 스탠다드 라이브러리로부터, 혹은 써드-파티 라이브러리 (third party libraries)로부터 import한다. 여러분들은 import 구문을 한 라인의 코드 (a one-liner)로써 아래와 같이 작성할 수 있다.

import "fmt"

만약 여러분들이 다수의 패키지들을 import하는 경우에, 괄호를 사용하는 것이 관례이다(idiomatic).

import (
  "fmt"
)

만약 여러분들이 fmt 패키지와 같은 Go 패키지들에 대한 문서를 읽어보고 싶다면, golang.org을 방문하여, documents을 클릭한 후, package documentation까지 스크롤을 내려서 fmt를 찾아 확인하면 될 것이다. 또한, godoc.org에서도 여러 라이브러리를 확인할 수 있는데, 위의 예시와 같은 fmt의 문서는 godoc.org/fmt에서 자세한 내용을 살펴볼 수 있다.

[godoc.org/het/http)(http://godoc.org/net/http), godoc.og/html/template, 등과 같은 다양한 예시들도 확인할 수 있다.

다시 돌아와 godoc.org/fmt 문서를 보도록 하자. 문서를 쭉 읽다 보면 index에 대한 내용을 확인할 수 있을 것이다. 이 내용은 종종 처음 문서에 접근할 때 유용하게 사용할 수 있는 부분이다. 대문자 첫 영문자로 시작하는 모든 것은 fmt패키지에서 exported 된 것들이며, 혹은 이를 패키지 외부(out side of the package)에서 visible 하다고 할 수 있다.

Go의 경우에 우리는 특별히 public/private과 같은 개념을 언급하지 않는다. 참고로, 위의 용어들은 다른 언어들에서 도입하고 있는 개념이다. Go의 경우에는 Exported/Not Exported, 패키지 외부에서 Visible/Not Visible한 지에 대한 여부에 대한 개념으로 명명하고 있다. 만약에 한 패키지 내의 하나의 함수의 이름이 대문자로 시작한다면, 이는 패키지 외부에서 visiable 하다는 것을 의미한다 (예를 들면 Println 함수).

우리는 fmt 패키지의 fmt.Println를 사용하고 있다. 이와 관련한 문서 fmt.Println를 보도록 하자.

func Println(a ...interface{}) (n int, err error)

"Println는 기본 포맷(default formats)을 사용하여 피연산자 (operands)를 스탠다드 아웃풋/표준출력(standard output)으로서 출력(write)한다. 공백들은 항상 피연산자들 사이에 항상 추가되고, 코드의 한 라인의 끝에 줄 바꿈 (newline)도 추가된다. 이는 출력된 바이트 수(the number of bytes)와 출력 오류가 있다믄 이를 반환한다."

일반적으로, Go에서는 우리는 항상 반환값들(returns)과 함께 작업들을 수행한다 (반드시 그럴 필요가 없는 경우도 존재한다). 저자가 완전하게 설명하기는 어려우나, 저자의 경험상 Println사용하면서 int값이나 err값을 함께 취득(capturing)하면서 사용한 것은 보지 않았다고 한다.

만약에 우리가 Println을 사용하면서 함께 반환되는 int값과 err값을 확인하고 싶다면 아래와 같이 코드를 작성하면 된다.

package main

import (
	"fmt"
)

func main() {
	n, err := fmt.Println("Hello, playground")
	fmt.Println(n, err)
}

그러나, 여러분든 아마도 반환된 값들을 사용하여 아래와 같은 코드도 작성할 수 있을 것이다.

package main

import (
	"fmt"
)

func main() {
	n, err := fmt.Println("Hello, playground")
	n2, err2 := fmt.Println(n, err)
}

보통 이런 방식으로 interr를 포착(capturing)하지는 않는다. 왜냐하면, 이와 같은 방법은 err를 포착하기 위해서 무한루프 (infinite loop)를 야기 할 수 있기 때문이다.

반환값 (things which are being returned)을 사용하지 않는 방법으로는, 여러분들이 그냥 반환값들을 void로서 버릴 수 있다. Go는 깨끗한 코드를 유지하기 위해서 무의미한 노력을 하지 않도록 설계되어 있기 때문이다.

코드가 지저분해 지는 것(code pollution) 을 방지하는 방법 중 하나는, 여러분들이 사용하지 않을 변수를 가지고 있지 않는 것이다. 위와 같은 경우, n2err2를 가지고 있으나 사용하고 있지 않는 상태에서 코드를 실행하려고 하기 때문에, Go 컴파일러는 에러를 반환한다.

package main

import (
	"fmt"
)

func main() {
	n, err := fmt.Println("Hello, playground")	
	_, _ := fmt.Println(n, err)
}

이를 실행하면 tmp/sandbox214796246/main.go:9: no new variables on left side of :=와 같은 오류가 발생한다. 이는 9번째 라인에서 새 변수를 선언하고 있지 않다는 의미이다. 그렇기 때문에 우리는 := 대신 =(the equal sign)을 사용할 수 있다. (이후에 short declaration에 대해서 학습 할 예정이다) 코드를 아래와 같이 수정하여 다시 컴파일 하고 실행하여 보도록 하자.

package main

import (
	"fmt"
)

func main() {
	n, err := fmt.Println("Hello, playground")
	_, _ = fmt.Println(n, err)
}

위의 코드는 아래와 같은 메시지를 출력한다.

Hello, playground
18 <nil>

위으 코드는 "Hello, playground"를 출력하고 위의 코드에서 선언한 변수 n으로서 해당 출력문의 바이트 값을 의미하는 18을 출력하고 또한 <nil> 이라고 반환된 err도 함께 출력하고 있다.

정리하면, fmt 패키지로부터 우리는 Println 함수를 사용해 보았다. 이는 variadic parameter로써 Go에서 정의하고 있는 모든 데이터 타입을 입력받을 수 있다. 인터페이스 (interfaces)에 대하여서는 이후에 자세하게 배우도록 하겠다. 만약에 여러분들이 3개의 점 ...과 함께 연달아서 하나의 데이터 타입을 보게 된다면, 이는 여러분들이 무제한으로 해당 타입에 대한 인수를 전달할 수 있다는 것을 의미한다. 여기서의 interface{}는 비어있는 인터페이스(empty interface)로 이해할 수 있다. Empty interface 모든 장소에서 구현되어 있기 때문에, 여기에 여러분들은 원하는 만큼 많은 값들을 콤마(,)를 사용하여 구별하는 것 만으로 Println 함수에 인수로서 임력할 수 있다. fmt.Println은 입력된 값들을 단치 출력하는 역할을 할 뿐이다.

결국, 우리가 원하는 만큼, 해당 함수에 다양한 변수값을 아래와 같이 입력할 수 있다.

package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello, playground", 42, "something else", true)
}

그리고 이는 문제없이 입력값들을 출력한다.

우리는 fmt 패키지로부터 정의된 Println에 대하여 간략히 알아보았다. 또한 관련 문서에 대하여도 살펴보았다. 강의 영상에서 가장 강조하고 싶은 점은 모든 Go 프로그램은 package main 내부로부터 프로그램이 시작하고, 이의 구체적인 시작점은 func main라는 점이다. 이러한 이유로, package main은 항상 func main을 가지고 있어야 한다.

func main은 여러분들의 Go 프로그램의 시작점(entrypoint)이고, 메인 함수는 여러본들의 프로그램이 종료될 때 까지 존재한다.

또한, 프로그램내에서 package.Identifier와 같은 점 표기법 (dot notation)을 사용하기도 한다. 이러한 identifier는 변수 (a variable), 상수 (a constant), 또는 함수 (a function)등을 위해서 사용할 수 있다.

영문 대문자로 시작하는 변수, 상수, 함수를 위한 모든 identifier는 모두 exported 되거나 패키지 외부에서 visiable 하다고 할 수 있다. Println은 영문 대문자 P로 시작되기 때문에, 우리가 해당 함수에 접근 (access)할 수 있다. 위 함수는 ...과 같은 variadic parameter를 취할 (take) 수 있고, 원하는 만큼 얼마든지 인자값 (argument)을 취할 (accept) 수 있다. 어떠한 타입(any type)도 될 수 있는, empty interface인 interface{}의 타입의 경우에는 콤마(,)를 사용하여 입력인자들을 구분해 준다.

다음 비디오에서는 format printing에 대하여 알아보도록 하겠다.