곱셈을 만들어주는 함수 만들어보기
일반적인 경우
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라는 것을 인식합니다.
그리고 함수 뒤 중괄호 전 자료형을 선언하는 것은 리턴값이 있다는 것을 의미하는데, 작성하지 않고 리턴을 할 수 없습니다.
필수적으로 명시를 해주어야 합니다.
정말 이상하지만 굉장히 매력적인 부분이라고 할 수 있습니다.
대부분의 프로그래밍 언어에서는 갖고있지 않은 방식이기 때문입니다.
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 형태로 값을 받을 수 있습니다.
이번에 알아볼 함수는 "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
는 앞으로도 자주 보게될 것이고 자주 쓰일겁니다.