Golang

[GoLang 시작하기 3] Naked Return과 Defer

여니여니_ 2020. 3. 17. 21:19

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
 
import (
    "fmt"
    "strings"
)
 
func lenAndUpper(name string) (int, string) {
    return len(name), strings.ToUpper(name)
}
func repeatMe(words ...string) {
    fmt.Println(words)
}
func main() {
 
    totalLength, upperName := lenAndUpper("yooyeon")
    fmt.Println(totalLength, upperName)
 
    repeatMe("yooyeon", "nico", "nudge", "lizard")
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

lenAndUpper 함수

이 함수는 이름 문자열을 입력받아 문자열의 길이와 문자를 대문자로 변환한 값을 반환해주는 함수이다.

name string 처럼 매개변수 name이 앞에오고 자료형 string이 뒤에 오는 것이 특이하다.

또, int, string 처럼 반환 값이 두개 이상 가능하고 매개변수 뒤쪽에 적어준다.

 

repeatMe 함수

여러개의 string 매개변수를 전달하여 출력하는 함수이다.

매개변수의 갯수를 미리 정하지 않으려면 앞에 ...을 붙이면 된다.

 

 

주의할 점은 Golang은 무엇을 만들고 사용하지 않으면 오류를 발생시킨다. (변수를 선언하고 사용하지 않는 등..)

 

 

naked return

1
2
3
4
5
6
7
 
func lenAndUpper(name string) (length int, uppercase string) {

    defer fmt.Println("I'm done")

    length = len(name)
    uppercase = strings.ToUpper(name)
    return
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

앞서 작성했던 함수 중 lenAndUpper 함수를 위와 같이 변형할 수 있다. 

naked return은 반환 값의 length uppercase 변수를 바로 리턴 가능하다.

return 뒤에 length, uppercase를 따로 써줄 필요 없다.

 

defer

defer는 함수가 종료되기 전까지 특정 구문의 실행을 지연시켰다가, 함수가 종료되기 직전에 지연시켰던 구문을 수행한다. 자바나 C#의 finally 같은 개념이다. 주로 리소스를 해제시키거나 클렌징 작업이 필요할 때 사용한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
 
import "fmt"
 
func main() {
    f1()
}
func f1() {
    fmt.Println("f1 - start")
    defer f2()
    fmt.Println("f1 - end")
}
func f2() {
    fmt.Printf("f2 - deferred")
}
 

 

이 함수의 출력값은 다음과 같다.

 

즉, f1함수를 끝까지 실행 후 f2를 실행하게 된다. 

 

단순한 호기심에서 f3도 한번 만들어 보았다. 다음의 경우는 출력이 어떻게 될까?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
 
import "fmt"
 
func main() {
    f1()
}
func f1() {
    fmt.Println("f1 - start")
    defer f3()
    defer f2()
 
    fmt.Println("f1 - end")
}
func f2() {
    fmt.Println("f2 - deferred")
}
func f3() {
    fmt.Println("f3 - deferred")
}
 

 

 

먼저 defer한 함수가 나중에 실행된다는 결과를 얻었다(?)

 

함수 하나에 defer 키워드를 여러 개 사용하면, 

defer로 지정한 각 구문은 스택(stack)에 쌓였다가 가장 나중에 쌓인 defer 구문부터 수행된다고 한다.