GO #4 - Functions Example(GO 함수 예제)

Corner·2022년 5월 15일
0

Go

목록 보기
5/9
post-thumbnail

Functions Part1

곱셈을 만들어주는 함수 만들어보기

일반적인 경우

func multiply(a, b) {
  return a * b
}

func main() {
  fmt.Println(multiply(3, 3))
}

이런 식으로 작성하면 코드 상으로 오류가 발생합니다.

문제점은 multiply() 함수에는 우선 매개변수에 자료형 타입이 들어가야하며, 바로 a * b 리턴을 하면 안됩니다.

컴파일러에게 int type을 리턴할 것이라는 것을 알려주어야 합니다.

func multiply(a int, b int) int {
   return a * b 
}

이렇게 말이죠.

이것을 조금이나마 축약형으로 고칠 수 있습니다. 매개변수에 둘다 같은 타입 "int" 자료형이라면

func multiply(a, b int) int {
  return a * b
}

이렇게 하면 Go Lang에서는 a, b가 int라는 것을 인식합니다.

그리고 함수 뒤 중괄호 전 자료형을 선언하는 것은 리턴값이 있다는 것을 의미하는데, 작성하지 않고 리턴을 할 수 없습니다.

필수적으로 명시를 해주어야 합니다.


GO는 여러개의 리턴값을 가질 수 있습니다.

정말 이상하지만 굉장히 매력적인 부분이라고 할 수 있습니다.

대부분의 프로그래밍 언어에서는 갖고있지 않은 방식이기 때문입니다.

예시

package main

import "strings"

func lenAndUpper(name string) (int, string) {
   return len(name), strings.ToUpper(name)
}

func main() {}

lenAndUpper() 라는 함수에는 string 자료형의 name을 매개변수로 받고, int타입과 string 타입으로 반환할 수 있습니다.

int 타입으로 반환하게 되면 string 타입의 길이를 알 수 있고, name을 대문자 string으로 변환할 수 있도록 strings.ToUpper라는 함수가 존재합니다.

strings라는 패키지 덕분입니다.

Go에는 아주 많은 패키지가 존재합니다. 표준 라이브러리가 너무나도 거대하기 때문에 거의 패키지로 모든 것을 처리할 수 있습니다.

👉 Go Standard library Docs를 참조하면 많은 것을 보게됩니다.

func main() {
 totalLength, upperName := lenAndUpper("corner") 
}

이런식으로 메인함수에서 작성하게 되면 컴파일 에러가 발생하는데 이유는 내가 무엇을 만들것인지에 대해 사용하지 않으면 에러가 발생합니다.

func main() {
   totalLength, upperName := lenAndUpper("corner")
   fmt.Println(totalLength, upperName)
}

그리하여 Println 함수를 사용하여 해당 변수를 사용해야합니다.

실행하게 되면 리턴 값을 받을 수 있습니다.

6 CORNER

ToUpper() 함수에 의해 대문자로 String 문자열로 반환된 것을 확인합니다.

하지만, 여기서 제가 글자 수만 알고 싶어서 totalLength 변수만 사용할 수 있을까요?

func main() {
  totalLength := lenAndUpper("corner"),
  fmt.Println(totalLength)
}

확인해보면 코드 상에서 에러가 발생합니다. lenAndUpper() 함수에서는 두 개를 리턴하기 때문입니다.

방법이 없는건 아닙니다. value를 무시할 수있는 코드를 작성합니다.

func main() {
  totalLength, _ := lenAndUpper("corner")
	fmt.Println(totalLength)
}

이렇게하면 리턴 값에서 totalLength변수만 사용이 가능합니다.

_ 라는 표식은 "이 value 값을 무시하겠다." 의미를 가지고 있으므로 알고 계셔야합니다.

한가지 더 함수에 대해 알아보겠습니다.

함수에서 여러 개의 arguments를 전달해 호출하는 방법입니다.

우선 repeatMe(words string){ } 함수를 만들고, 메인 함수에서 repeatMe("..", "..", "...")로 요청하게 되면

repeatMe(words ...string) {} 으로 무한의 args를 받을 수 있습니다.

package main

import "fmt"

func repeatMe(words ...string) {
	fmt.Println(words)
}

func main() {
	repeatMe("corner", "developer", "moon", "suwon")
}
실행결과::
[corner developer moon suwon]

그저 Type 앞에 ... 3개의 점(.)을 찍으면 아주 예쁜 Array 형태로 값을 받을 수 있습니다.


Functions part2

이번에 알아볼 함수는 "naked" return 입니다.

위에서 만들어 본 lenAndUpper함수를 만들어보겠습니다.

import (
   "fmt"
   "strings"
)

func lenAndUpper(name string) (length int, uppercase string) {
   length = len(name)
   uppercase = strings.ToUpper(name)
   return
}

func main() {
   totalLength, up := lenAndUpper("corner")
   fmt.Println(totalLength, up)
}

여기서 lenAndUpper() 함수를 보면 return 명시해주는 곳에 (lenght int, uppercase string)이라고 지정한 이유는, "선언과 동시에 해당 변수값을 리턴하겠다"를 의미합니다.

보시다시피 함수 내에 변수를 선언하지 않았음을 알 수 있습니다.

컴파일을 돌려보면 실행 결과는 똑같습니다.

6, CORNER

위에서 리턴할 변수를 지정했기 때문에 함수 내에서 리턴할 때 변수명을 굳이 명시하지 않아도 됩니다.

이번에는 "defer"이라는 함수를 보겠습니다.

이것은 function이 끝났을 때 무엇을 동작하도록 할 수 있습니다.

기존에 lenAndUpper()함수가 끝나고나서 문자열을 출력해보도록 합니다.

func lenAndUpper(name string) (length int, uppercase string) {
   defer fmt.Println("Done...")
   length = len(name)
   uppercase = strings.ToUpper(name)
   return
}

defer는 이 함수가 끝나고 난 뒤 행동입니다.

func lenAndUpper(name string) (length int, uppercase string) {
   defer fmt.Println("Done...")
   length = len(name)
   uppercase = strings.ToUpper(name)
   fmt.Println("함수")
   return
}

func main() {
   totalLength, up := lenAndUpper("corner")
   fmt.Println("----------")
   fmt.Println(totalLength, up)
}

실행결과 ::

함수
Done...
----------
6 CORNER

함수가 리턴되기 전 출력문 "함수"가 실행 -> 함수가 끝났다는 defer의 "Done..." 실행 -> main 함수에서 출력문을 마지막으로 실행합니다.

어느정도 이해가 되시나요?

defer는 앞으로도 자주 보게될 것이고 자주 쓰일겁니다.

profile
Full-stack Engineer. email - corner3499@kakao.com,

0개의 댓글