티스토리 뷰
func 함수명(매개변수) (반환타입 또는 반환값) {
...
}
Go에서 함수는 func 키워드 + 매개변수 + 반환타입을 순으로 선언한다.
매개변수를 생략할 수 있고, 반환값이 없을 때도 반환 값을 표기하는 부분이 없어도 된다.
func function(s string, a, b, c int) {
...
}
변수 선언과 마찬지로 매개변수도 [변수 이름 + 타입]과 같이 표기한다. 여러 개의 매개변수를 선언할 때 같은 타입이 있다면 [매개변수1, 매개변수2, ..., 매개변수n, 변수타입]과 같은 형식으로 표기할 수 있다.
func function(integers ...int) {
...
}
C++과 마찬가지로 go에도 가변 인자를 사용할 수 있다. 매개변수 타입 앞에 ...을 사용하여 여러 개의 값을 배열로 받을 수 있다.
import "fmt"
func return_one() int {
return 1;
}
func return_two() (int, int) {
return 1, 2;
}
func main() {
fmt.Println(return_one())
one, two := return_two()
fmt.Println(one, two)
}
go에서 하나 이상의 값을 리턴할 수 있다. 단, 두 개 이상일 때는 반환값을 괄호로 묶어서 표기한다.
go의 함수에는 수행 결과와 에러 상태, 이렇게 두 개 이상 리턴하는 경우가 많다. 정상적으로 수행되면 nil을, 아닌 경우에는 에러 상태를 리턴한다.
문자열을 정수로 변환해 주는 Atoi 함수이다. 문자열을 받아서 int와 error 2개의 값을 리턴한다.
import (
"fmt"
"strconv"
)
func convertStringToInt(s string) {
if v, e := strconv.Atoi(s); e != nil {
fmt.Printf("%s는 정수가 아닙니다.\n", s);
} else {
fmt.Printf("%d는 정수입니다.\n", v);
}
}
func main() {
convertStringToInt("1024") // 1024는 정수입니다.
convertStringToInt("hello") // hello는 정수가 아닙니다.
}
위의 코드를 보면 두번째 converStringToInt 함수를 호출할 때 hello는 nil이 아닌 error을 리턴한다. 따라서 두번째 호출해서는 "hello는 정수가 아닙니다."가 출력된다.
func return_numbers() (int, int, int) {
return 1, 2, 3;
}
func main() {
num, _, _ := return_numbers()
fmt.Println(num)
}
go에는 _로 표기하는 blank identifier이 있다. go 컴파일러는 blank identifier을 변수로 인식하지 않는다.
return_numbers는 3개의 숫자를 리턴한다. 그리고 1만 필요할 때는 2와 3은 blank identifier을 사용하여 처리해주면 된다.
func returnNum() (num int) {
num = 1
return
}
func main() {
num := returnNum()
fmt.Println(num) // 1
}
함수 선언부에는 리턴 값의 이름과 타입이 명시되어 있고, 함수 바디에 return 키워드 뒤에는 값이 있지 않다. 위의 코드를 실행하면 1이 출력되는 것을 확인할 수 있다.
return 뒤에 따로 표기하지 않아도, 선언부에 리턴 값의 이름이 표기되어 있다면 해당 이름을 가지는 것이 리턴된다.
go는 call by value 방식으로 값을 호출한다.
💡call by value
함수를 호출할 때 인자에 변수 자체를 전달하는 것이 아닌, 값을 복사해서 전달하는 것
함수로 매개변수의 값을 변경하기 위해서는, 주소 연산자 &와 참조 연산자 *를 사용하면 된다.
func plusOne (num *int) {
*num = *num + 1 // 포인터를 통한 값 참조
}
func main() {
num := 99
plusOne(&num) // 주소를 전달
fmt.Println(num)
}
&를 사용하여 변수의 주소 값을 알 수 있고, *로 포인터를 만들어서 해당 값을 변경하면 된다.
func main() {
plus := func(x, y int) int {
return x + y
}
fmt.Println(plus(1, 2)) // 3
func(x, y int) {
fmt.Println(x + y) // 7
}(3, 4)
}
go에서는 이름을 지정하지 않는 익명 함수, 클로저가 있다.
클로저를 활용해서 변수에 함수를 넣을 수도 있고, 바로 호출할 수도 있다.
func makeSuffix(suffix string) func(string) string {
return func(name string) string { // 익명함수 호출
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
func main() {
addZip := makeSuffix(".zip")
addTgz := makeSuffix(".tar.gz")
fmt.Println(addZip("go"))
fmt.Println(addTgz("go"))
}
위는 factory method이다. makeSuffix는 익명 함수를 리턴하고, makeSuffix 함수로 addZip, addTgz 함수를 만들었다.
func printOne () {
fmt.Println(1)
}
func printTwo () {
fmt.Println(2)
}
func printN(print func()){
print()
}
func main() {
num := 1
if num == 1 {
printN(printOne)
} else if num == 2 {
printN(printTwo)
}
}
go에서는 매개변수로 함수를 전달할 수 있다. 매개변수의 타입을 func()로 표현을 해줘야 한다.
go의 기본 라이브러리 중 strings.IndexFunc도 매개변수로 문자열과 함수를 받는다. 문자열에서 문자를 하나씩 차례대로 함수에 적용했을 때 true가 리턴되면, 해당 인덱스를 리턴한다.
import (
"fmt"
"strings"
"unicode"
)
func main() {
f := func(c rune) bool {
return unicode.Is(unicode.Hangul, c)
}
fmt.Println(strings.IndexFunc("Hello, 월드", f)) // 7
fmt.Println(strings.IndexFunc("Hello, world", f)) // -1
}
f는 문자가 한글이면 true를 리턴한다. 한글이 있는 문자열은 인덱스를 리턴하였고 없는 문자열은 -1을 리턴하였다.
defer
defer 키워드가 붙은 구문은 스택에 차례대로 쌓였다가 함수가 종료되기 직전에 실행된다.
func stack() {
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
}
func def() {
defer fmt.Print("Go!\n")
fmt.Print("Hello ")
}
func main() {
def() // Hello Go!
stack() // 4 3 2 1 0
}
def 함수를 보면 Hello 출력하는 구문이 더 뒤에 있지만 Go를 출력하는 구문보다 먼저 실행되는 것을 알 수 있다.
stack 함수를 보면 처음에 나왔던 0이 가장 나중에 출력되고, stack에 호출된 구문들이 쌓이는 것을 알 수 있다.
defer을 사용하는 것 보다 처음에 순서를 잘 맞춰서 사용하면 좋을 것 같지만, defer은 사용하는 경우가 있다.
<defer을 사용하는 예>
- 파일 스트림 닫기
- 리소스 잠금 해제하기
- 레포트에서 Footer 출력하기
- 데이터베이스 커넥션 닫기
위의 경우 파일을 읽고, 그 밑에 줄에 defer을 사용하여 닫아주면 사용하기 편하고 가독성도 좋아진다.
- Total
- Today
- Yesterday
- postman
- pm.test
- Kotlin
- python3
- 코딩테스트
- pm.expect
- downTo
- Squash and merge
- 코틀린
- postman tests
- 확장 함수
- java
- Basic Type
- graphql
- github
- postman collection
- squash merge
- string
- 주생성자
- hashcode
- DGS Framework
- Kotlin In Action
- git
- 1차 인터뷰
- Python
- mysql
- 2차 인터뷰
- go 특징
- solidity
- 네이버 2022 공채
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |