Golang 기초 (5) : 함수에 대하여

Eon Kim·2021년 12월 9일
0

Golang 기초 

목록 보기
5/14
post-thumbnail

안녕하세요, 주니어 개발자 Eon입니다.

이번 포스트에서는 함수에 대해서 다루겠습니다.

📌 함수 : function

함수는 수학에서 f(x) 로 표현합니다.
그리고 함수 f(x)는 어떠한 수식을 담고 있습니다.
f(x) = x + 5
f(3) = 3 + 5 = 8
이렇게 표현하곤 합니다.
컴퓨터에서의 함수는 언어마다 사용하는 방법만 조금 다를 뿐, 수학에서의 함수와 다를 바 없습니다.
입력값에 대한 출력값, 이게 함수입니다.
f(x)라는 함수에 입력값 3를 넣어, 함수의 동작으로 5를 더한 뒤, 출력값 8이 반환되었습니다.

컴퓨터에서의 함수 또한 입력값과 반환값으로 되어 있고, 이를 사용해 프로그램을 구성합니다.


📍 The rule of naming in Golang

Golang에서 변수나 함수의 이름을 작성하는 방법은 정해져 있어, 매우 쉬운 편입니다.
(그저 이름을 뭐로 지을지가 고민일뿐..)

현재 패키지 외부에서도 쓰일 수 있게 하려면 대문자로, [Unicode upper case letter (Unicode class "Lu");]
현재 패키지 내부에서만 쓰일 수 있게 하려면 그 외의 문자로 시작하면 됩니다.

이는 사용자 간의 약속이 아닌 Golang 자체적 기능으로 분류된 것입니다.
영대문자가 아닌 문자로 선언된 변수나 함수는 전부 외부 패키지에서 다룰 수 없습니다.
go.dev/ref/spec#Exported_identifiers

변수나 함수를 한글로 이름 짓기

Golang은 기본 인코딩이 UTF-8입니다.
따라서, 한글로 된 이름도 선언이 가능합니다.

UTF-8 문자로 패키지 외부에서 사용할 수 있게 하려면 반드시 문자 앞에 영대문자를 붙여주어야 합니다.
"한글함수" => "A한글함수"
"한글변수" => "A한글변수"


📍 The format of function in Golang

Golang에서의 함수는 다음과 같이 사용할 수 있습니다.

func NameOfFunc(a int, b int) (isTrue bool) {
	isTrue = (a == b)
	return
}
  • func : function(함수)의 약자로, 함수를 정의할 때 꼭 포함해야 함
  • NameOfFunction : 함수의 이름이며, 영대문자로 시작하기 때문에 외부 패키지에서도 사용이 가능함
  • (a int, b int) : 함수 내에서 사용될 매개변수 a와 b를 각각 int로 선언함
  • (isTrue bool) : 함수의 반환값을 변수 isTrue로 하며, 해당 변수는 bool 타입임
  • { ... } : 함수의 내용을 적는 파트이며, 자유롭게 작성함
  • isTrue = (a == b) : 비교 연산자 '=='으로 변수 a와 b가 동일한지 체크함
    • a == b 가 참일 때는 true, 거짓일 때는 false를 반환함
  • return : 값을 반환함 -> 반환할 값을 변수 isTrue로 지정했기 때문에 변수명을 적지 않아도 됨

아래는 같은 기능을 하는 함수를 다르게 표현함


func nameOfFunc(a, b int) bool {
	isTrue := (a == b)
	return isTrue
}
  • nameOfFunc : 함수 이름이며, Lu class 문자가 아니기 때문에 외부 패키지에서 불러올 수 없음
  • (a, b int) : 변수 a와 b 모두 int타입이라, 한 번에 선언함
  • bool : 반환값의 타입만 명시하고 반환할 값은 지정하지 않음
  • isTrue := (a == b) : isTrue 변수를 (a == b) 결과값에 맞는 타입으로 선언함
  • return isTrue : bool 타입 변수인 isTrue를 반환함

참고 : Golang에는 삼항 연산자가 없다. return (a == b) ? true : false 를 하고 싶으나, Golang에서는 불가하다.
go.dev/doc/faq#Does_Go_have_a_ternary_form


📍 The usage of function in Golang

Golang에서 함수를 사용하는 방법은 다음과 같습니다.

프로젝트에서 위와 같이 직접 작성하거나, 외부 패키지를 임포트하여 해당 패키지의 함수를 사용할 수 있습니다.

아래는 main 함수에서 위에 작성한 함수를 사용하는 방법입니다.

package main

import "fmt"

func nameOfFunc(a, b int) bool {
	isTrue := (a == b)
	return isTrue
}

func main() {
	isOk := nameOfFunc(3, 5)
	fmt.Println(isOk)
}
  • package main : main 패키지이며, 해당 프로그램의 진입 패키지임
  • import "fmt" : 아래 main 함수에서 결과값 출력을 위해 import함
  • func main() { ... } : main 함수는 매개변수와 반환값이 없어야 함; 프로그램 실행 시, 가장 먼저 실행되는 함수라서 어떠한 매개변수도 전달받지 않으며, main 함수의 내용이 순차적으로 실행되고 main 함수가 모두 실행되면 프로그램이 종료됨
  • isOk := nameOfFunc(3, 5) : isOk라는 변수를 선언하며 값으로는 nameOfFunc(3, 5)의 반환값을 넣음
  • nameOfFunc(3, 5) : nameOfFunc() 함수에 매개변수 3과 5를 전달하며, 이는 각각 위의 nameOfFunc() 함수의 변수 a와 b로 사용됨

이렇게 여러 가지 기능을 함수로 구현하고, 그 기능들을 복합적으로 활용하여 프로그램이 만들어집니다.


📍 The recursive function in Golang

recursive function은 재귀함수라고 합니다.
함수 자기 자신이 자기 자신을 다시 호출하는 방식입니다.
이 방식은 call stack이 많이 쌓일 수 있어서 그리 선호되는 방식은 아닙니다.

위 그림과 같이 main()에서 recursiveAddFunc()를 호출하고, 그 안에서 다시 recursiveAddFunc()을 호출하고, 그 안에서 ...

이렇게 반복되다가 탈출 조건을 만나고, 값을 return할 때,

한 번에 해당 값이 main()으로 반환되는 것이 아니라 콜스택 가장 위에 있는 함수에서 이전 함수로 반환하고, 그리고 또 이전 함수로 반환하고, 그리고 또 이전 ...

결국 최종적으로 얻고 싶었던 값조차 재귀함수가 호출된 횟수만큼 return을 거쳐야 하기 때문에 비효율적입니다.
가급적 반복적인 기능 수행이 필요한 경우에는 반복문을 통해서 수행하고, 재귀함수는 꼭 필요한 때에만 사용하도록 하는 게 좋습니다.

Golang에서 재귀함수는 다음과 같이 구현할 수 있습니다.

package main

import "fmt"

func recursiveAddFunc(a, b int) int {
	a += b
	if a < 100 {
		fmt.Println("Before recursive call, a is :", a)
		a = recursiveAddFunc(a, b)
		fmt.Println("After recursive call, a is :", a)
	}
	return a
}

func main() {
	fmt.Println(recursiveAddFunc(5, 3))
}
  • a += b : a에 b를 더한 값을 a에 대입함
  • if a < 100 { ... } : a가 100보다 작을 때, 조건문 내의 내용을 수행함; 이 코드의 재귀함수 탈출 조건으로 사용되었으며, a가 100보다 커지면 if 조건문을 넘어가서 return a 를 수행함
    (추후 다른 포스트에서 다룰 내용임)
  • a = recursiveAddFunc(a, b) : 재귀함수 호출을 하고, 반환값을 a에 대입함
  • func main() { fmt.Println(recursiveAddFunc(5, 3)) } : recursiveAddFunc(5, 3)의 반환값을 출력함

위의 코드 실행으로, 재귀함수 동작을 이해하기 좋습니다.


📍 예제 : Calculator 계산기

아래는 Golang으로 만든 간단한 사칙연산 계산기 프로그램입니다.
아직 조건문에 대한 내용을 다루지 않아 함수로만 구현하였고, 한 번에 모든 연산에 대한 결과를 출력하는 프로그램입니다.

package main

import "fmt"

func addFunc(a, b int) int {
	return a + b
}
func subFunc(a, b int) int {
	return a - b
}
func mulFunc(a, b int) int {
	return a * b
}
func divFunc(a, b int) int {
	return a / b
}
func modFunc(a, b int) int {
	return a % b
}
func main() {
	var x, y int
	fmt.Println("write two values to calculate..")
	fmt.Println("format : 'value1 value2' then 'press Enter'")
	fmt.Scanf("%d %d", &x, &y)
	fmt.Println("result of addFunc(x, y) is :", addFunc(x, y))
	fmt.Println("result of subFunc(x, y) is :", subFunc(x, y))
	fmt.Println("result of mulFunc(x, y) is :", mulFunc(x, y))
	fmt.Println("result of divFunc(x, y) is :", divFunc(x, y))
	fmt.Println("result of modFunc(x, y) is :", modFunc(x, y))
}

실행 후, 연산을 수행할 값 두 개를 입력하면 결과가 출력됩니다.


이번 포스트는 함수에 대한 내용이었습니다.
Go도 익명함수가 있습니다. 다만 나중에 다루도록 하겠습니다.
감사합니다.👍

profile
주니어 개발자

0개의 댓글