Doodly IT
[Go 묘공단 스터디] 21. 함수 고급편 본문
1. 가변인수 함수
package main
import "fmt"
func sum(nums ...int) int {
sum := 0
fmt.Printf("nums 타입: %T\n", nums)
for _, v := range nums {
sum += v
}
return sum
}
func main() {
fmt.Println(sum(1, 2, 3, 4, 5))
fmt.Println(sum(10, 20))
}
함수를 전달하는 매개변수에 ...키워드로 함수의 매개변수를 가변적으로 사용할 수 있다.
대표적인 예로도 Print함수도 매개변수가 가변인자이다.
func Printf(format string, a ...any) (n int, err error) {
return Fprintf(os.Stdout, format, a...)
}
2. defer 지연실행
package main
import (
"fmt"
"os"
)
func main() {
f, err := os.Create("test.txt") // 1
if err != nil { //2
fmt.Println("Fail to create a file")
return
}
defer fmt.Println("반드시 호출이 됩니다.")//7
defer f.Close()//6
defer fmt.Println("파일을 닫았습니다")//5
fmt.Println("파일에 HelloWorld를 씁니다")//3
fmt.Fprintln(f, "Hello World")//4
}
defer 키워드를 쓰면 해당 함수가 종료되기 직전에 실행이 되도록 지연이 된다.
defer 키워드 문을 쓴 명령문은 역순으로 실행이 된다. Create함수는 파일을 생성하는 함수로 파일 이름을 적어주면(string) output으로 파일 객체와 에러를 보낸다. 이때 파일이 정상적으로 실행이 되면 err은 nil형태이다.
아래는 Create가 참조하는 함수의 리턴형을 참고하기위한 자료이다.
func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
<대략 에러가 생기면 error에 에러를 내보내라는 코드>
if e != nil {
return nil, &PathError{Op: "open", Path: name, Err: e}
}
return f, nil
}
3. 함수타입 변수
함수 타입 변수는 함수 포인터 이다.
package main
import (
"fmt"
)
func add(a, b int) int { // add 함수
return a + b
}
func sub(a, b int) int { // sub 함수
var tmp int
if a > b {
tmp = a - b
} else if a < b {
tmp = b - a
} else {
tmp = 0
}
return tmp
}
func getOperator(op string) func(int, int) int {
if op == "+" {
return add
} else {
return sub
}
}
func main() {
var operation func(int, int) int
operation = getOperator("+")
var result = operation(3, 4)
fmt.Println(result)
}
중요한 부분은 func getOperator (op string) func (int ,int) int 이 부분이다.
다른 언어와 마찬가지로(사실 다른언어라 해봤자 C뿐이지만) 함수 형태를 적어주면 될것같다.
예를 들어 C언어에서도 함수포인터는 아래와 같이 쓴다.
//함수를 파라미터로 하는 함수
int def(int , int (*func)(int a, int b){ ... }
//위 함수의 매개변수로 들어가는 함수는 아래와 같다.
int handler(int a, int b) {...}
아래 구문에서 함수 이름인 handler를 없애고 대신에 함수포인터를 써서 함수의 주소값을 연결해주는 것이 C타입이라면,
똑같이 함수의 이름을 없애면서 함수의 포인터 대신에 func로 함수가 매개변수임을 명시하는게 Go이다.
//함수를 파라미터로 하는 함수
func def (int a) func(int, int) int{...}
//위 함수에 매개변수가 되는 함수
func handler(int a, int b) int {...}
이때 func(int, int) int {...} 부분을 별칭으로 재지정할 수 있다.
type opFunc(int, int) int
func getOperation(op string) opFunc{ ... }
4. 함수 리터럴
package main
import "fmt"
func main() {
i := 0
f := func() { // 함수의 정의를 변수에 대입
i += 10
}
i++
f() // 함수 호출
fmt.Println(i)
}
함수 리터럴은 이름이 없는 함수로 함수명을 적지않고 함수 타입 변숫값으로 바로 대입하는 형태로라고 말한다.
다른 언어에서는 익명함수 또는 람다함수라고 불린다.
'프로그래밍 > Go' 카테고리의 다른 글
[Go 묘공단]27. 객체 지향의 원칙 SOLID (1) | 2023.12.20 |
---|---|
[Go 묘공단 스터디] 22. 자료구조 (1) | 2023.12.06 |
[Go 묘공단 스터디] 인터페이스 (0) | 2023.11.29 |
[Go 묘공단 스터디] 메서드 (0) | 2023.11.29 |
[Go 묘공단 스터디] 슬라이스 (0) | 2023.11.29 |