9.3. 프로그램언어 고(Go)의 함수 리턴값 처리하기

프로그램언어 고(Go)에서의 기본적인 함수 리턴값 처리 방법

고(Go)에서 함수의 리턴값을 처리하는 기본적인 방법은 다음과 같습니다.

package main

import "fmt"

func add(x, y int) int {
   result := x + y
   return result
}

func main() {
   sum := add(1, 2)
   fmt.Println(sum) 
}

위 예제코드에서 add 함수는 두 정수를 받아서 덧셈 결과를 리턴합니다.
main 함수 내에서는 add 함수를 호출하고 결과값을 sum 변수에 할당하여 저장합니다.

이러한 방식으로 고(Go)에서 함수의 리턴값을 변수에 할당하여 저장하고 사용할 수 있습니다.

리턴값을 받는 변수의 타입은 함수의 리턴 타입과 맞춰야 정상 작동합니다. 위 예제의 add 함수는 정수를 리턴하므로 결과값을 받을 변수도 정수형이어야 합니다.

func sum(nums []int) int {
  result := 0
  for _, num := range nums {
    result += num
  }
  return result
}

func main() {
  numbers := []int{1, 2, 3} 
  sumValue := sum(numbers)
  fmt.Println(sumValue)
}  

위의 다른 예제에서는 슬라이스를 전달받아 합계를 계산하는 sum 함수가 있습니다.
main 함수에서는 numbers 슬라이스를 인자로 넘겨서 합계 결과값을 sumValue 변수에 할당하고 있죠.

이처럼 리턴값을 저장하는 변수는 함수의 반환 값 타입과 일치해야합니다.

또한 리턴값을 무시하고 사용하지 않을 수도 있습니다.

func printHello() {
  fmt.Println("Hello Go!")
}

func main() {
  printHello()
}

위 예제의 printHello 함수는 아무값도 리턴하지 않습니다. 단순히 문장을 출력할 뿐입니다.
main에서 단순히 함수를 호출하기만 하고 있습니다.

이처럼 함수의 리턴값이 필요없다면 변수에 저장하지 않고 값을 버릴 수 있습니다.

고(Go)에서 함수의 리턴값을 처리하는 기본적인 방법은 위와 같습니다.
함수 호출 후 리턴값을 변수에 할당하여 저장하고 사용하는 것이 일반적입니다.

함수의 반환 값 타입에 맞춰 결과값을 받을 변수를 선언하시기 바랍니다.

고(Go) 함수 리턴값에 대한 설명 여기까지입니다. 친절한 설명이 되었길 바랍니다.

프로그램언어 고(Go)에서의 다중 리턴값 처리 방법

프로그램언어 고(Go)에서는 하나의 함수가 다중의 값을 리턴할 수 있습니다. 이를 통해 복잡한 데이터 구조체를 리턴할 필요없이 간단하게 여러 값을 리턴할 수 있습니다.


package main

import "fmt"

func returnMultiValues() (int, int) {
    return 10, 20
}

func main() {
    a, b := returnMultiValues()
    fmt.Println(a, b)
}

위의 예제코드에서 returnMultiValues() 함수가 int 형식의 값 2개를 리턴하고 있습니다.
main() 함수에서 이 값들을 a, b 변수에 각각 할당받아 사용하고 있습니다.

다중값 리턴 시에는 함수 정의부에서 리턴할 변수들의 타입을 모두 지정해주어야 합니다.


func 함수이름(매개변수) (리턴타입1, 리턴타입2) {
    ...
    return 값1, 값2
}

위 코드의 형태로 작성하면 되며, 값 리턴 시에도 타입 순서대로 값을 리턴해주어야 합니다.

값을 받아올 변수도 리턴하는 타입 순서대로 선언하여 받아주면 됩니다.


변수1, 변수2 := 함수이름()

이런 형태로 값을 할당 받으면 순서대로 변수에 리턴값들이 대입됩니다.

다중값 리턴은 복잡한 데이터 구조체를 리턴하는 것보다 코드가 간결해지고 가독성도 높아집니다.
함수 기능별로 값들을 구분지어 리턴할 수 있어 유용합니다.

함수에서 에러처리를 해야하는 경우에도 에러 변수를 같이 리턴하여 처리할 수 있습니다.


func 함수이름(매개변수) (타입1, 타입2, error) {
	...
	if 에러가 있다면 {
		return 값1, 값2, 에러
	}
	return 값1, 값2, nil
}

이런 형태로 에러 변수를 같이 리턴하는 코드를 작성할 수 있습니다.

다중값 리턴은 고(Go) 언어의 아주 큰 장점 중 하나이므로 꼭 활용할 수 있도록 연습하는 것이 좋습니다.

프로그램언어 고(Go)에서의 리턴값이 있는 함수의 결과를 변수로 받기

고(Go)언어에서 함수가 리턴값을 가지는 경우, 그 리턴값을 변수에 저장할 수 있습니다. 이를 위해서는 다음과 같은 문법을 사용하시면 됩니다.

func 함수이름(매개변수들) 리턴타입 {
    // 함수 본문
    return 리턴값
}

funcCallResult := 함수이름(인자들)

예를 들어, 정수 두 개를 입력받아 더한 값을 리턴하는 함수가 있다면 다음과 같이 작성할 수 있습니다.

func sum(a, b int) int {
    return a + b
}

result := sum(1, 2) // result = 3

위 예제의 sum 함수는 두 개의 int형 매개변수 a, b를 입력받아 이를 더한 값을 int형으로 리턴합니다.

그리고 main 함수에서는 sum 함수를 호출하면서 1과 2를 인자로 넘겨줬습니다.

sum 함수의 실행 결과인 리턴값 3을 result 변수에 저장하고 있습니다.

이처럼 고(Go)언어에서는 함수 실행 후 리턴되는 값을 변수에 저장할 수 있습니다.

이러한 기능을 사용하면 함수의 실행 결과를 저장하고 활용할 수 있기 때문에 매우 유용합니다.

지금 설명드린 내용이 함수의 리턴값을 변수에 저장하는 방법에 대한 전반적인 이해에 도움이 되셨기를 바랍니다.

프로그램언어 고(Go)에서의 리턴값으로 에러처리하기

Go 언어에서 리턴값으로 에러를 처리하는 방법은 주로 다음과 같습니다.

func 함수이름(매개변수) (반환타입, error) {
	// 함수 본문

	if 에러가발생했다면 {
		return nil, errors.New("에러 메시지") 
	}

	return 반환값, nil
}

위의 코드처럼 함수의 반환값을 2개로 정의하고, 첫 번째 반환값은 정상 출력, 두 번째 반환값은 error 타입 입니다.

정상적으로 작동했다면 nil을, 에러가 발생했다면 errors.New를 사용하여 error 객체를 만들어 리턴합니다.

func connectToDB() (dbConnection, error) {
	conn, err := sql.Open("mysql", "user:password@/dbname")
	if err != nil {
		return nil, errors.New("DB 연결 실패")
	}

	return conn, nil 
}

func main() {
	conn, err := connectToDB()
    
	if err != nil {
		fmt.Println(err)
		return
	}

	// 정상 실행
} 

위의 예제에서 DB 연결 함수 connectToDB()는 dbConnection과 error를 반환합니다.

정상 연결 시 nil을, 연결 실패 시 실패 사유 메시지를 에러로 반환하여 호출한 쪽에서 이를 처리할 수 있도록 했습니다.

main() 함수에서 반환된 에러를 확인하고, 에러가 있을 경우 에러 메시지 출력 및 처리를 하고 있습니다.

이처럼 Go언어에서는 별도의 exception 처리가 없고, 반환값으로 에러 체크를 하여 처리할 수 있습니다. 코드가 직관적이고 편리한 장점이 있습니다.

또한 errors 패키지를 사용하여 상세한 에러 정보를 제공할 수도 있습니다.

프로그램언어 고(Go)에서의 리턴값을 이용한 비동기 처리 방법

Go언어에서 비동기 처리를 위해 리턴값을 이용할 수 있습니다. 가장 대표적인 방법이 goroutine과 channel을 사용하는 것입니다.

goroutine은 Go언어의 경량스레드입니다. 함수를 goroutine으로 실행하면 별도의 고루틴에서 비동기적으로 실행됩니다.

func printHello() {
  fmt.Println("hello") 
}

func main() {
  go printHello() // printHello 가 별도 고루틴에서 실행
}

위와 같이 go 키워드를 사용하여 함수를 goroutine으로 실행할 수 있습니다.

그리고 channel을 사용하여 고루틴 간 통신을 할 수 있습니다.

func sum(a []int, c chan int) {
  total := 0
  for _, v := range a {
    total += v
  }
  c <- total // channel로 결과 전달 
}

func main() {
  a := []int{1,2,3,4,5}
  c := make(chan int)
  
  go sum(a[:len(a)/2], c)  
  go sum(a[len(a)/2:], c)  

  x, y := <-c, <-c // channel로 결과 수신

  fmt.Println(x, y, x+y) 
}

위 예제처럼 함수의 결과를 channel을 통해 전달받아 결과를 처리할 수 있습니다. sum 함수에서 생산된 결과값을 channel c로 보내고, main함수에서 channel c로 결과값을 받습니다. 이를 통해 비동기적으로 처리될 수 있습니다.

goroutine만 생성하고 결과를 받지 않으면 결과를 확인할 수 없기 때문에, channel을 사용하여 결과값을 리턴받는 것이 중요합니다.

또한 WaitGroup을 사용하여 goroutine의 완료를 기다릴 수 있습니다.

func process(i int, wg *sync.WaitGroup) {
  fmt.Println("Start process : ", i)
  time.Sleep(1 * time.Second) // 처리 시간 필요
  fmt.Println("Done process : ", i)    
  wg.Done() 
}

func main() {  
  var wg sync.WaitGroup

  for i := 0; i < 3; i++ {
    wg.Add(1)
    go process(i, &wg)  
  }

  wg.Wait() // goroutine완료 기다림  

  fmt.Println("All Done!")
}

위 예제에서 WaitGroup을 사용하여 모든 goroutine이 완료될 때까지 기다리고 있습니다. 이를 통해 동기화도 가능합니다.

이 외에도 Context를 사용하여 goroutine을 취소할 수도 있습니다.

Goroutine과 Channel 등의 기법을 사용하면 Go언어로 효과적인 비동기 처리를 할 수 있습니다. 주의할 점은 결과 처리를 위해 반드시 결과값을 리턴받거나 동기화하는 로직이 필요하다는 것입니다.

고맙습니다.

Leave a Comment