일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 개발자
- 스프링
- JPA
- framework
- database
- 그리디알고리즘
- Java
- 자바
- 그리디
- 읽기쉬운코드
- 엘라스틱서치
- 클린코드
- cleancode
- API
- 알고리즘
- 코드
- 애자일기법
- 백준
- 프레임워크
- Spring
- 데이터베이스
- Elasticsearch
- 코딩
- 애자일
- 애자일프로그래밍
- 개발
- spring boot
- ES
- 코딩테스트
- Baekjoon
- Today
- Total
튼튼발자 개발 성장기🏋️
기본 문법 본문
변수, 상수 그리고 열겨형
변수를 선언할 때 변수 명에는 공백을 포함하지 않은 문자, 숫자, 언더스코어(_)를 사용할 수 있고 숫자는 첫 글자에 사용할 수 없다. golang에서는 대소문자를 구분한다는 점에 유의해야한다. 참고로 golang은 camel case를 사용하는 것을 권장한다.
변수를 선언하는 방법은 크게 4가지가 있다.
- var 키워드로 선언하고 var 다음에 변수 이름과 타입을 표기한다.
- 같은 타입인 변수를 선언할 경우 콤마(,)로 구분하여 선언할 수 있다.
- 서로 다른 타입의 변수를 선언할 경우 소괄호로 묶어서 한 번에 선언할 수 있다.
- 변수 선언과 동시에 값을 정의할 경우 타입을 생략할 수 있고, := 연산자를 사용할 수도 있다.
var a int
var b string
var name, age, address string
var (
name string
age int
weight dloat
)
var c = true
name := "small-goliath"
상수란 처음 선언한 이후 변하지 않는 변수를 의미한다. 상수의 경우에는 const 키워드를 사용하여 선언할 수 있다. 상수는 bool, 숫자, 문자열 타입으로만 선언할 수 있다.
상수는 컴파일할 때 값이 정해진다. 특정 계산식의 결과를 상수로 지정할 수 있는데, 이런 계산식은 컴파일할 때 연산할 수 있어야한다.
const limit - 64
const max unit64 = 1024
const max = 1024 * 1024
const = getNumber() // 유효하지 않음
const (
RED = 0
ORANGE = 1
YELLOW = 2
)
golang은 특이하게도 다른 언어에서 기본적으로 사용하는 개면을 사용하지 않는 경우가 많다. 열거형이 그 중 하나인데, 상수와 열거형에 차이를 두지 않는다.
상수를 선언할 때 iota 예약어를 사용하면 편리하다. 상수를 그룹으로 묶어서 선언할 때, const 그룹에서 iota의 값은 0이고 이후로는 1씩 증가하는 개념이다.
const (
RED = iota // 0
ORANGE // 1
YELLOW // 2
)
흐름제어
흔히 다른 언어처럼 if문, switch문, for문, select문으로 나눌 수 있는데 select문의 경우에는 병행 처리 코드를 작성할 때 채널을 제어하기 위해 사용되므로 기본 문법에서 다루기엔 양이 상당해서 다음에 언급 하도록 하겠다.
조건문
if문의 조건식에는 bool type만 사용이 가능하기 때문에 0과 1은 조건식에 사용할 수 없다. 조건문을 제어하는 break, continue, goti, return이 등장할 때는 else를 생략하면 간결해질 수 있다.
if문에는 초기화 구문도 작성할 수 있는데, 초기화 구문과 조건식은 세미콜론(;)으로 구분하며 초기화 구문에서 선언된 변수는 if문 내에서만 사용할 수 있다.
is := true
not := false
if is {
// ...
} else if not {
// ...
} else {
// ...
}
if v := compute(); v < 0 {
fmt.Println(v, "는 음수입니다.")
}
switch문도 마찬가지로 중괄호가 필수이다. 값을 둘 이상 사용할 때는 콤마로 구분해주어야한다.
일치하는 case문을 만나면 break가 없어도 바로 switch 문을 빠져나오는 점에 유의해야한다. 이 때, 다음 case로 넘어가려면 fallthrough를 사용해야한다.
만약 switch문에 변수를 사용하지 않으면 첫 번째로 true인 case 조건을 실행한다.
switch i {
case -1, -2:
fmt.Println(i, "는 음수입니다.")
case 1, 2:
fmt.Println(i, "는 양수입니다.")
default:
fmt.Println(i, "는 0입니다.")
}
switch i {
case 1:
fmt.Println("i는 1보다 작거나 같습니다.")
fallthrough
case 2:
fmt.Println("i는 2보다 작거나 같습니다.")
fallthrough
case 3:
fmt.Println("i는 3보다 작거나 같습니다.")
}
i := -2
switch {
case i < 0:
fmt.Println(i, "는 음수입니다.") // 실행
case i == 0:
fmt.Println(i, "는 0입니다.")
case i > 0:
fmt.Println(i, "는 양수입니다.")
}
반복문
golang에는 while문이 없다. 보통 상황에 따라서 for문과 while문을 사용하는데, golang은 모든 반복문을 for문으로 사용한다.
초기화 구문, 조건식, 후속 작업은 세미콜론으로 구분하게 되는데, 모든 구문은 생략할 수 있다.
for문에 레이블을 사용하여 식별자를 붙일 수 있으며 break를 더 유용하게 사용할 수 있다.
for i := 0; i < COUNT; i++ {
// ...
}
for {
// ...
}
i = 11
sum = 0
LOOP:
for {
i -= 1
if i%2 == 1 {
sum += i
break LOOP
}
}
함수
golang은 call by value가 기본이다. 이에 유의하여 함수를 작성해야하며 call by reference를 사용해야할 때 포인터와 주소 값을 잘 활용해야한다. (C언어와 동일)
함수의 접근제어, 매개변수, 익명함수, 클로저 등에 관한 내용을 알아보자.
기본적으로 func 키워드로 선언하며 함수명과 매개변수, 반환 타입 또는 반환 값이 위치한다.
func 함수명(매개변수) (반환타입 또는 반환 값) {
// ...
}
매개변수가 여러 개일 경우 콤마로 구분하여 작성하며 같은 타입인 매개변수가 여러 개이면 매개변수 이름을 콤마로 구분한다. golang의 경우에도 가변인자를 사용할 수 있는데 닷(.) 세개를 사용하여 나타낸다.
func myFunc(b bool, s string, i, j, k int, num ...int) {
// ...
}
golang은 python과 비슷하게 하나 이상의 값을 리턴할 수 있다. 리턴 값이 두 개 이상일 경우에만 괄호를 사용하여 리턴한다. 만약 필요 없는 리턴값이라면 언더 스코어를 사용하여 ignore할 수 있다.
func myFunc() int {
return 10
}
func myFunc2() (int, string) {
return (10, "십")
}
num, name := myFunc2()
num, _ := myFunc2() // 두 번쨰 리턴값 무시
defer 키워드는 함수가 종료되기 전까지 특정 구문의 실행을 지연시켰다가 함수가 종료되기 직전에 수행한다. 주로 리소스를 해제시키거나 클렌징 작업이 필요할 때 사용한다.
func main() {
WhatIsDefer()
}
func Defer() {
fmt.Println("Defer END!")
}
func WhatIsDefer() {
fmt.Println("WhatIsDefer() START!")
defer Defer()
fmt.Println("WhatIsDefer() END!")
}
/*
WhatIsDefer() START!
WhatIsDefer() END!
Defer END!
*/
때로는 함수 이름을 지정하지 않고 사용하는 익명함수를 사용할 때가 있다. golang에서 함수는 일급 객체이므로 변수의 값으로 사용할 수 있다. 다음과 같이 함수를 변수에 할당하여 변수처럼 사용할 수 있다.
아래 예제 코드를 보면 마지막에 (1, 1)로 함수를 호출한 것을 볼 수 있는데 이런 익명 함수를 클로저라 한다.
fplus := func(x, y int) int {
return x + y
}
fmt.Println(fplus(1, 1))
fmt.Println(func(x, y int) int {
return x + y
}(1, 1))
// closure
addZip := ClosureName(".zip")
addTar := ClosureName(".tar")
fmt.Println(addZip("Clo"))
fmt.Println(addTar("sure"))
함수를 매개변수로 전달할 수도 있다.
func main() {
FuncArgs(3, Display3)
}
func FuncArgs(num int, f func(int, string)) {
f(num, "나를 출력해줘")
}
func Display3(num int, str string) {
fmt.Printf("num: %d, str: %s\n", num, str)
}
init() 함수는 패키지가 로드될 때 가장 먼저 호출되는 함수로, 패키지의 초기화 로직이 필요할 때 선택적으로 사용할 수 있다.
package main
import (
"fmt"
)
var v rune
func init() {
v = '1'
fmt.Println("init 함수는 패키지가 로드될 때 호출된다.")
}
func main() {
// ...
}