관리 메뉴

A seeker after truth

Golang 기본(2) - 반복문, 함수, 익명함수 본문

Programming Language/Golang(Go)

Golang 기본(2) - 반복문, 함수, 익명함수

dr.meteor 2019. 10. 12. 00:02

*본문은 <예제로 공부한 go 프로그래밍>(http://golang.site/go/basics) 사이트를 참고하여 공부하면서 정리한 내용입니다. Tip 위주로 간략하게 정리했으며, 보탬 내용은 <Go 디스커버리>(염재현 저, 한빛미디어, 2016)을 참고하여 작성되었습니다.

 

8. 반복문

//for문은 다른 언어와 같은 형식을 쓴다.

//단, for(~~~~) 이렇게 괄호를 이용하면 에러!

sum := 0

for i:=1; i<=100; i++ {

  sum += i

}

 

//while문이 따로 없고 조건식만 쓰는 for문으로 그를 대체한다.

n:=1

for n<100 {

  n*=2

}

 

//infinite loop

for { //ctrl C 누르면 out

//...

}

 

//for~range문

//range 컬렉션으로부터 원소의 값&인덱스를 리턴하여 for에 있는 변수들에 할당한다.

names:=[]string{"a","b","c"}

for index,name:=range names{

  println(index,name)

}

 

//break, continue, goto

/*break는 for 외에도 switch, select문에서도 사용 가능하다. 하지만 continue문은 for루프와 연관되어 사용.

또한, break는 지정된 레이블로 이동하는 것도 가능하게 한다.*/

i := 0

L1:

for {

  if i == 0 {

    break L1

  }

}



 

9. 함수

func main() {

  msg := "hi"

  say(msg)

}

/*msg값이 복사되어 say 함수로 전달된다. 따라서 msg값이 say 함수 내에서 변경된다하더라도 호출함수 main에서의 msg 변수는 변함이 없다.*/

func say(msg string){ //함수의 리턴 타입은 이 위치에 적는다

  println(msg)

}

 

//포인터를 전달하고자 한다면 다음과 같이 작성하면 된다. 알다시피 이땐 값 바꾸면 제대로 바뀜

func main() {

  msg := "hi"

  say(&msg)

  println(msg)

}

 

func say(msg *string) {

  println(*msg)

  *msg = "Changed"//msg가 포인터 변수이기 때문에 *를 붙이면 ** 상쇄되어 값 변경이 가능하다는 점 알지?

}



variadic function(가변인자함수)

//타입은 정해져 있지만, 받는 파라미터 수가 정해져 있는 건 아닌 경우

func main(){

  say("This","is","a","book")

  say("hi")

}

 

func say(msg ...string){

  for _, s := range msg {

    println(s)

  }

}

 

//고도 파썬처럼 여러 개의 리턴값을 지원한다. 타입을 다음과 같이 표기해야 한다.

func main(){

  count, total := sum(1,3,5,7,9)

  println(count, total)

}

func sum(nums ...int) (int, int) {

  s := 0

  count := 0

  for _, n := range nums {

    s += n

    count++

  }

  return count, s

}

 

/*Named Return Parameter라고 하여, 리턴값이 여러 개일 때 코드 가독성을 높이는 장점이 하나 있다. 위 함수를 이 버전으로 고쳐쓰면 다음과 같다.*/

func sum(nums ...int) (count int, total int) {

  for _, n := range nums {

    total += n

  }

  count = len(nums)

  return

}//실제 return문에는 아무 값을 리턴하지 않지만, 그래도 리턴되는 값이 있을 경우엔 빈 return 문을 반드시 써주어야 한다. 안그럼 에러



 

10. 익명함수

/*함수명을 갖지 않는 함수를 익명함수라고 한다. 일반적으로 그 함수 전체를 변수에 할당하거나 다른 함수의 파라미터에 직접 정의되어 사용되곤 한다. 전자의 경우 변수명이 함수명과 같이 취급되며 "변수명(파라미터들)" 형식으로 함수를 호출할 수 있다.*/

func main() {

  sum := func(n ...int) int {

    s := 0

    for _, i := range n {

      s += i

    }

    return s

  }//익명함수 끝

 

  result := sum(1,2,3,4,5) //익명함수 호출

  println(result)

}



//일급 함수

/*그냥 평범한 함수를 일급함수라고 하며, 이는 고의 기본 타입과 동일하게 취급되며 다른 함수의 파라미터로 전달하거나 다른 함수의 리턴값으로도 사용될 수 있다.

아! 글고 아까 중요한 걸 빼먹었다. 호출하는 함수와 호출 대상 함수의 선후 관계는 상관없다고 한다 이거 진짠가...*/

func main() {

  //변수 add에 익명함수를 할당하는 방법

  add := func(i int, j int) int {

    return i+j

  }

  r1 := calc(add, 10, 20)

  println(r1)

 

  //함수 내 파라미터에서 익명함수를 정의함

  r2 := calc(func(x int, y int) int {return x-y}, 10, 20)

  println(r2)

}

func calc(f func(int,int) int, a int, b int) int {

  result := f(a,b)

  return result

}



//type문을 사용한 함수 원형 정의

/*type문은 구조체, 인터페이스 등 custom type(사용자 정의 타입)을 정의하기 위해 사용된다. type문은 또한 함수 원형을 정의하는데 사용될 수 있다. 위 예제에서 계속 반복되는 func(x int, y int) int를 함수 원형이라 하여 이를 type문으로 정의할 수 있다.

이렇게 함수의 원형을 정의하고 함수를 타 메서드에 전달하고 리턴받는 기능을 타 언어에서 흔히 delegate라고 부른다.*/

type calculator func(int, int) int

func calc(f calculator, a int, b int) int {

  result := f(a,b)

  return result

}