Golang 기초 (7) : 반복문에 대하여

Eon Kim·2021년 12월 30일
0

Golang 기초 

목록 보기
7/14
post-thumbnail

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

이번에 다룰 내용은 반복문입니다.

Golang에서의 반복문은 오로지 for를 사용하는 방법만 존재합니다.
물론 이 for문을 어떻게 사용하느냐에 따라 다른 언어에 존재하는 반복문 형태를 손쉽게 구현할 수 있습니다.

📌 반복문

반복문은 코드의 반복을 위해 존재합니다.
간단한 작업같아도 반복된 작업을 해야 할 때, 우리는 반복문을 사용합니다.
이는 코드의 간결화, 가독성 확보를 위해 꼭 필요합니다.
반복문의 사용은 이중, 삼중으로도 사용이 가능한데 너무 많이 겹쳐두는 것은 좋지 않습니다.
가독성도 좋지 않고, 유지•보수하기 좋지 않습니다.
제 경우엔 삼중을 최대로 두려고 합니다.

그렇다고 겹겹이 쌓인 반복문을 함수로 처리하는 게 좋은가?
그건 또 아닙니다. 콜스택이 쌓이면 퍼포먼스에서 미세하게 차이가 날 수 있으므로 적절한 타협이 필요합니다.
물론 퍼포먼스에 큰 차이는 없지만 극한의 퍼포먼스를 보장해야 하는 상황이라면 직접 테스트하고 사용해야 합니다.

만약, 반복문이 여러 번 반복된다면 해당 역할을 하는 함수를 작성해서 처리하는 방법이 코드의 간소화 및 유지•보수를 위해 좋을 것입니다.

반복문이 있음으로써 할 수 있는 것들은 무궁무진합니다.
가령, 1부터 1000까지의 정수를 출력할 때에도 1000줄을 쓰느냐, 3줄을 쓰느냐는 큰 차이입니다.


📝 반복문의 종류와 사용

위에서 말씀드린 것처럼 Go에서는 for문만을 제공합니다.
하지만, 이 for문으로 표현할 수 있는 반복문의 종류는 여러 가지 있습니다.
Effective go에서는 Golang의 반복문을 이와 같이 설명하고 있습니다.
Golang에는 do-while이 없습니다.


📍 for init; condition; post {...} : C-Like for

for i := 0; i < 1000; i++ {
	fmt.Printf("%d ", i)
}
/* The result of output
0 1 2 3 ... (중략) 999 
*/

for 선언; 조건; 후처리 작업 {...}

C언어에서 사용하듯이 위와 같이 작성할 수 있습니다.
가장 기본적인 형태이며, 제어하기 가장 쉬운 형태라고 볼 수 있습니다.


📍 for condition {...} : C-Like while

i := 0
for i < 1000 {
	fmt.Printf("%d ", i)
}
/* The result of output
0 1 2 3 ... (중략) 999 
*/

for 조건 {...}

C언어에서 사용하는 while문을 이렇게 표현할 수 있습니다.
위의 for문은 i < 1000이라는 조건을 만족하는 중에만 실행됩니다.
{...}안에 i값을 증가시키거나 다른 특정한 조건을 넣어, i값을 1000보다 큰 값으로 만들어 루프(반복문)를(을) 탈출할 수 있습니다.
(아래에 소개하는 break를 이용해서 탈출할 수도 있습니다.)


📍 for {...} : C-Like for(;;)

i := 0
for {
	if i >= 1000 {
		break
	}
	fmt.Printf("%d ", i)
	i++
}
/* The result of output
0 1 2 3 ... (중략) 999 
*/

C언어에서 사용하는 무한 루프를 이렇게 표현할 수 있습니다.
아무런 조건이 없어, 그저 무한으로 반복되는 루프입니다.
탈출 조건을 명시하지 않으면 컴퓨터의 리소스를 모두 사용할 때까지 무한히 반복됩니다.
위의 코드에서는 i의 값이 1000 이상일 경우, break를 실행하게 했습니다.
break문을 실행하면 루프를 탈출하게 됩니다.


📍 for - range : 'for loop' for array, slice, string, or map, or reading from a channel

var array [4]string
array[0] = "Hi"
array[1] = "this"
array[2] = "is"
array[3] = "array"
for i, v := range array {
	fmt.Printf("index : %d \t value : %s \n", i, v)
}
/* The result of output
index : 0        value : Hi 
index : 1        value : this 
index : 2        value : is 
index : 3        value : array 
*/

for 인덱스, 요소 := range 배열 {...}

(array, slice, string, map, channel은 아직 다루지 않은 내용이므로 추후 포스팅할 때 링크 걸어두도록 하겠습니다.)
간단하게 위에 사용된 array에 대해서만 설명하겠습니다.
array는 '배열'이며, 값들을 저장합니다.

  1. 변수 array를 string 타입 4개짜리 배열로 선업합니다.
  2. 각 인덱스 요소에 string 타입 값을 넣습니다. 이 때, 인덱스는 0부터 시작해서 3까지만 넣을 수 있습니다.
    (값을 넣지 않은 요소에는 zero-value(기본값)가(이) 들어갑니다.)
  3. for를 사용해, 배열의 인덱스와 요소들을 모두 순차적으로 출력합니다.

for-range 문은 아래와 같이 사용할 수 있습니다.

for i, v := range array {...}

  • 인덱스, 요소 모두를 사용해야 할 때 사용합니다.

for i := range array {...}

  • 인덱스만 사용할 때 사용합니다.

for _, v := range array {...}

  • 요소만 사용할 때 사용합니다.

📍 for - range : 'for loop' for strings

for i, v := range "yes, array" {
	fmt.Printf("index : %d \t value : %c \n", i, v)
}
/* The result of output
index : 0        value : y 
index : 1        value : e 
index : 2        value : s 
index : 3        value : , 
index : 4        value :   
index : 5        value : a 
index : 6        value : r 
index : 7        value : r 
index : 8        value : a 
index : 9        value : y 
*/

for 인덱스, 요소 := range "문자열" {...}

위와 같이 평범한 strings에 대해서도 사용이 가능합니다.
이 때, v로 받는 값이 각 문자가 되며, 문자 출력을 위해 %c를 사용합니다.


📍 'for loop' with parallel assignment

a := [4]string{"Hi", "this", "is", "array"}
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
	a[i], a[j] = a[j], a[i]
}
for i, v := range a {
	fmt.Printf("index : %d \t value : %s \n", i, v)
}
/* The result of output
index : 0        value : array 
index : 1        value : is 
index : 2        value : this 
index : 3        value : Hi 
*/

for 변수1, 변수2 := 변수1의 값, 변수2의 값; 조건식; 변수1, 변수2 = 변수1에 대한 계산식, 변수2에 대한 계산식 {...}

C언어에서 위와 같이 배열의 순서를 뒤바꾸기 위해서 우리는 'tmp'라는 변수를 만들어 사용하곤 했습니다.
Golang에서는 그럴 필요 없이 '병렬 할당'을 이용하면 됩니다.

병렬 할당

a, b := 1, 100

위의 코드는 좌항 a와 b에, 우항 1과 100을 순차적으로 할당합니다.


📍 'loop' using Label

	var i int = 0
Label1:
	if i >= 1000 {
		goto Label2
	}
	fmt.Printf("%d ", i)
	i++
	goto Label1
Label2:
	fmt.Println("finished")
    /* The result of output
    0 1 2 3 ... (중략) 999 finished
    */

레이블명:
레이블명은 대소문자 관계없이 지정할 수 있다.

Label은 위와 같이 사용할 수 있습니다.
레이블은 특정한 조건에 실행해야 하는 코드를 감싸고 있는 플래그라고 보시면 됩니다.
또, 루프의 기능을 하기 위해 만들어진 것은 아니기 때문에 goto를 사용해 특정 Label로 이동하는 것을 볼 수 있습니다.


📍 'for loop' using Label 2

	var i int = 0
Label1:
	for {
		if i >= 1000 {
			break Label1
		}
		fmt.Printf("%d ", i)
		i++
	}
	fmt.Println("finished")
    /* The result of output
    0 1 2 3 ... (중략) 999 finished
    */

Golang에서는 위와 같이 루프에 Label을 붙이고 해당 Labelbreak해서 탈출할 수 있습니다.



📌 반복문의 탈출

반복문을 특정한 조건이 되면 그만두고 싶을 때, 탈출 조건을 명시해야 한다고 했습니다.
탈출 뿐만 아니라, 특정 조건에서의 반복문 점프도 가능합니다.


📝 반복문 탈출의 종류와 사용

반복문을 제어하기 위해 사용할 수 있는 것들은 continue, break, goto가 있습니다.


📍 break : to escape current loop

무한 루프가 아니더라도 반복문을 수행하다가 특정 조건에 해당 반복문을 빠져나와야 할 때 사용합니다.

a := 0
for {
	if a >= 10 {
		break
	}
	a++
}
fmt.Println("value of a :", a)
/* The result of output
value of a : 10
*/

위와 같이 무한 루프에서는 break를 사용해서 '현재'루프를 탈출합니다.
만약 이중 for문을 사용했고 가장 안 쪽 루프에서 break를 사용했다면 가장 안 쪽 루프만 탈출하게 됩니다.


📍 continue : to skip current iteration

반복문을 짜다 보면 특정 조건에서 넘어가게 만들어야 할 때가 있습니다.
그럴 때 continue는 유용하게 쓰입니다.

b := 0
for {
	if b < 10 {
		b++
		continue
	}
	fmt.Println("value of b :", b)
	break
}
/* The result of output
value of b : 10
*/

b는 0부터 시작해, 1씩 증가합니다.
또, if조건문 이후에 나오는 결과 출력하는 부분이 있습니다.
하지만, 0부터 9까지는 continue를 만나게 돼, 출력 파트는 실행되지 않습니다.


📍 goto : to go to specific Label in the code

반복문 소개하며 보여드린 Label 파트와 중복되는 부분입니다만 goto를 다시 소개하겠습니다.

	c := 0
	for {
		if c >= 10 {
			goto Label1
		}
		c++
	}
Label1:
	fmt.Println("value of c :", c)
/* The result of output
value of c : 10
*/

역시 무한 루프를 돌다가 조건이 만족하면 goto Label1로 Label1으로 이동하여 루프를 탈출합니다.


📍 break Label : to escape from the Label loop

이 역시 위에서 한 번 언급이 있었으나, 다시 한 번 소개하겠습니다.

	d := 0
Loop1:
	for {
		if d >= 10 {
			break Loop1
		}
		d++
	}
	fmt.Println("value of d :", d)
/* The result of output
value of d : 10
*/

무한 루프에 레이블을 지정했고, 특정 조건에 break Loop1을 통해 Loop1 레이블에서 탈출할 수 있게 했습니다.
이렇게 루프에 레이블을 지정하면 특정 조건에 다시 해당 레이블로 이동해서 코드를 동작할 수 있다는 장점이 있습니다.
물론 위와 같이 탈출 조건을 명시해서 여러 번 사용할 수도 있습니다.


이번 포스트는 반복문에 대한 내용이었습니다.
감사합니다.👍

profile
주니어 개발자

0개의 댓글