Go

Go 기본 문법

알맹리 2023. 7. 23. 20:43

1. 변수와 상수
2. 연산자
3. 자료형
4. 콘솔 출력과 입력 함수
5. 반복문
6. 조건문
7. 분기문

8. 제어문
9. 컬렉션
10. 함수

 

구름에듀의 '한 눈에 끝내는 고랭 기초' 강의를 참고했습니다.

1. 변수와 상수

콘솔 출력 함수의 기본

Go에서는 꼭 fmt 패키지를 임포트 하지 않아도 기본적으로 콘솔 출력 함수인 println, print를 지원합니다.

println은 호출 후 개행을 하고, print는 하지 않는다는 차이가 있습니다.

 

fmt 패키지

콘솔 출력을 위해 가장 많이 쓰이는 함수인 Println과 Print가 있습니다.

Printf 함수는 서식 문자를 활용하여 원하는 포맷으로 데이터를 출력할 때 사용합니다.

package main

import "fmt"

func main() {
    var num1 int = 1
    var num2 int = 2
    
    fmt.Print("Hello goorm!", num1, num2, "\n")
    
    fmt.Println("Hello goorm!", num1, num2)
	
    fmt.Printf("num1의 값은:%d num2의 값은:%d\n", num1, num2)
}

 

변수의 선언과 초기화

변수 선언; var 변수이름 변수형

Short Assignment Statement := 를 사용하면 별다른 형선언 없이 타입 추론이 가능합니다.

var a int = 1
var b string = "Hello"

c := 1
d := "Hello"

변수를 선언만 하고 초기값을 설정하지 않으면 'Zero value'로 설정됩니다.

  • bool타입; false
  • 숫자 타입; 0
  • string타입; ""

변수를 선언만 하고 사용하지 않으면 에러가 발생하고 컴파일에 실패합니다. 변수뿐만 아니라 패키지, 함수 등 모든 선언에 동일하게 적용됩니다. 

 

package main

import "fmt"

var globalA = 5 // 함수 밖에서는 'var' 키워드를 입력하고 변수 선언

func main() {
	var a string = "groom"
    fmt.Println(a)
    
    var b int = 10
    fmt.Println(b)
    
    var d = true
    fmt.Println(d)
    
    var e int
    fmt.Println(e)
    
    f := "short"
    fmt.Println(f)
    
    fmt.Println(globalA)
}

주석은 // 또는 /* */를 사용합니다.

 

package main

import "fmt"

func main() {
	var a, b int = 10, 20
    fmt.Println(a, b)
    
    i, j, k := 1, 2, 3
    fmt.Println(i, j, k)
    
    var str1, str2 string = "Hello", "world"
    fmt.Println(str1, str2)
}

같은 타입을 가지는 여러 개 변수를 한 번에 선언할 수 있습니다.

변수 개수와 초기화하는 값의 개수는 같아야 합니다.

 

상수의 선언과 초기화

상수는 변수와 다르게 한 번 초기화되면 그 뒤에 수정될 수 없습니다. 따라서 선언과 동시에 초기화를 해야 합니다.

상수는 명시하는 것 자체에 의미가 있기 때문에 사용하지 않아도 에러가 발생하지 않습니다. := 용법을 사용할 수 없습니다.

const 상수이름 상수형

 

package main
import "fmt"

const username = "kim"

func main() {
	const a int = 1
    const b, d = 10, 20
    const c = "hi"
    
    fmt.Println(username)
}

 

상수는 괄호를 이용해 여러 개의 값을 묶어서 초기화할 수 있습니다.

/* 
const (
	상수이름1 = 값1
    상수이름2 = 값2
    ...
) */

package main
import "fmt"

const (
	c1 = 10 // 첫 번째 값은 무조건 초기화해야 함
    c2
    c3
    c4 = "hi" // 다른 타입 선언 가능
    c5
    c6 = iota // c8까지 index값 저장
    c7
    c8
    c9 = "earth"
    c10
    c11 = "End"
)

func main() {
	fmt.Println(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11)
}

괄호로 묶여있는 상수들은 서로 다른 타입으로 초기화될 수 있습니다.

괄호 시작과 마지막의 위치는 상관 없으나 각 상수는 개행하여 초기화해야 합니다. 

각 상수 사이에는 콤마를 입력하면 안 됩니다.

묶어서 선언하는 상수들 중 첫번째 값은 꼭 선언돼야 하며, 선언되지 않은 값은 바로 전 상수의 값을 가집니다.

iota라는 식별자를 값으로 초기화하면 그 후에 초기화하지 않고 이어지는 상수들은 index(0부터 시작)가 값으로 저장됩니다.

 

2. 연산자

수식 연산자

+, -, *, /, %

+연산자는 문자열 포함, 나머지는 정수, 실수, 복소수

 

package main

import "fmt"

func main() {
	num1, num2 := 17, 5
	str1, str2 := "Hello", "world"
	
	fmt.Println("num1 + num2 =", num1+num2)
	fmt.Println("str1 + str2 =", str1+str2)
	fmt.Println("num1 - num2 =", num1-num2)
	fmt.Println("num1 * num2 =", num1*num2)
	fmt.Println("num1 / num2 =", num1/num2)
	fmt.Println("num1 % num2 =", num1%num2)
}

 

증감 연산자

값을 1만큼 증가시키거나 감소시키는 연산자입니다.

증감 연산자를 사용하고 동시에 대입하거나(num := count++), 전위 연산(++count)을 할 수 없습니다.

++, --

package main
import "fmt"

func main(){
	count1, count2 := 1, 10.4
    
    count1++
    count2--
    
    fmt.Println("count1++ :", count1)
    fmt.Println("count2-- :", count2)
}

 

할당 연산자

값을 단순히 대입하는 대입 연산자와 연산 후 값을 대입시키는 복합 대입 연산자가 있습니다.

종류 기능 설명
= 변수나 상수에 값 대입 변수는 변수끼리 대입 가능
:= 변수 선언 및 대입  
+= 값을 더한 후 대입 문자열의 경우 현재 변수에 문자열을 이어 붙인 다음 대입
-= 값을 뺀 후 대입  
*= 값을 곱한 후 대입  
/= 값을 나눈 후 대입  
%= 값을 나눈 나머지를 대입  
&= 값의 AND 비트 연산 후 대입  
|= 값의 OR 비트 연산 후 대입  
^= 값의 XOR 비트 연산 후 대입  
&^= 값의 AND NOT 비트 연산 후 대입  
<<= 비트를 왼쪽으로 이동 후 대입  
>>= 비트를 오른쪽으로 이동 후 대입  
package main
import "fmt"

func main() {
	a := 2
	var num int

	num = a
	fmt.Println("num = a :", num)
	num += 4
	fmt.Println("num += 4 :", num)
	num -= 2
	fmt.Println("num -= 2 :", num)
	num *= 5
	fmt.Println("num *= 5 :", num)
	num /= 2
	fmt.Println("num /= 2 :", num)
	num %= 3
	fmt.Println("num %= 3 :", num)

	num = 3  //00000011
	num &= 2 //00000010
	fmt.Printf("num &= 2 : %08b, %d\n", num, num)
	num |= 5 //00000101
	fmt.Printf("num |= 5 : %08b, %d\n", num, num)
	num ^= 4 //00000100
	fmt.Printf("num ^= 4 : %08b, %d\n", num, num)
	num &^= 2 //00000010
	fmt.Printf("num &^= 2 : %08b, %d\n", num, num)
	num <<= 9 //00001001
	fmt.Printf("num <<= 9 : %08b, %d\n", num, num)
	num >>= 8 //00001000
	fmt.Printf("num >>= 8 : %08b, %d\n", num, num)
}

 

논리 연산자

논리부정 연산시 bool 타입 선언 및 사용만이 가능합니다.

&&; AND

||; OR

!; NOT

package main
import "fmt"

func main() {
	var a bool = true
	b := false

	fmt.Println("0 && 0 : ", b && b)
	fmt.Println("0 && 1 : ", b && a)
	fmt.Println("1 && 1 : ", a && a)
	fmt.Println("0 || 0 : ", b || b)
	fmt.Println("0 || 1 : ", b || a)
	fmt.Println("1 || 1 : ", a || a)

	fmt.Println("!1 ", !true)
	fmt.Println("!0 ", !false)
}

 

관계 연산자

종류 기능 설명
== 두 값이 같은지 비교한다. 같을 경우 ‘true’, 다를 경우 ‘false’를 반환한다.
!= 두 값이 다른지 비교한다. 다를 경우 ‘true’, 같을 경우 ‘false’를 반환한다.
< 오른쪽 값이 큰지 비교한다. 오른쪽 값이 큰 경우 ‘true’, 그렇지 않을 경우 ‘false’를 반환한다.
<= 오른쪽 값이 크거나 같은지 비교한다. 오른쪽 값이 크거나 같은 경우 ‘true’, 그렇지 않을 경우 ‘false’를 반환한다.
> 왼쪽 값이 큰지 비교한다. 왼쪽 값이 큰 경우 ‘true’, 그렇지 않을 경우 ‘false’를 반환한다.
>= 왼쪽 값이 크거나 같은지 비교한다. 왼쪽 값이 크거나 같은 경우 ‘true’, 그렇지 않을 경우 ‘false’를 반환한다.
package main
import "fmt"

func main() {
	fmt.Println("13 == 13 : ", 13 == 13)
	fmt.Println("13 == 23 : ", 13 == 23)
	fmt.Println("13 != 13 : ", 13 != 13)
	fmt.Println("3 != 5 : ", 3 != 5)
	fmt.Println("0 < 1 : ", 0 < 1)
	fmt.Println("0 > 1 : ", 0 > 1)
	fmt.Println("0 >= 1 : ", 0 >= 1)
	fmt.Println("0 <= 1 : ", 0 <= 1)
}

 

비트 연산자

비트 단위의 연산을 하는 연산자 입니다. 

종류 기능 설명
& 두 값을 비트 단위로 AND 연산을 한다.  
| 두 값을 비트 단위로 OR 연산을 한다.  
^ 두 값을 비트 단위로 XOR 연산을 한다. 사용할 수 있는 값의 자료형은 정수입니다.
&^ 두 값을 비트 단위로 AND NOT 연산을 한다. 사용할 수 있는 값의 자료형은 정수입니다.
<< 값의 비트 열을 왼쪽으로 이동시킨다. 사용할 수 있는 값의 자료형은 정수입니다.
<< 값의 비트 열을 오른쪽으로 이동시킨다. 사용할 수 있는 값의 자료형은 정수입니다.
package main
import "fmt"

func main() {
	num1 := 15 //00001111
	num2 := 20 //00010100

	fmt.Printf("num1 & num2 : %08b, %d\n", num1&num2, num1&num2)
	fmt.Printf("num1 | num2 : %08b, %d\n", num1|num2, num1|num2)
	fmt.Printf("num1 ^ num2 : %08b, %d\n", num1^num2, num1^num2)
	fmt.Printf("num1 &^ num2 : %08b, %d\n", num1&^num2, num1&^num2)

	fmt.Printf("num1 << 4 : %08b, %d\n", num1<<4, num1<<4)
	fmt.Printf("num2 >> 2 : %08b, %d\n", num2>>2, num2>>2)
}

 

채널 연산자

채널은 채널과 고루틴(goroutine)끼리 데이터를 주고 받고 실행 흐름을 제어하는 기능입니다.

채널 연산자는 채널을 사용할 때 쓰는 연산자입니다.

<- 채널에 값을 보내거나 가져오는 등 채널의 수신을 연산합니다.

package main

import "fmt"

func main() {
	ch := make(chan int) //정수형 채널 생성

	go func() {
		ch <- 10
	}() //채널에 10을 보냄

	result := <-ch //채널로부터 10을 전달받음
	fmt.Println(result)
}

 

포인터 연산자

C++ 언어와 같이 &, * 연산자를 이용해 메모리에 접근할 수 있도록 합니다.

Go 언어는 포인터 연산자를 제공하지만 포인터에 더하고 뺴는 기능은 제공하지 않습니다.

종류 기능 설명
& 변수의 메모리 주소를 참조한다.  
* 포인터 변수에 저장된 메모리에 접근하여 값을 참조한다.  
package main

import "fmt"

func main() {
	var num int = 5
	var pnum = &num

	fmt.Println("num : ", num)   //num 값
	fmt.Println("pnum :", pnum)  //num의 메모리 주소
	fmt.Println("pnum :", *pnum) //num의 주소로 메모리에 할당돼있는 값 접근

	*pnum++
	fmt.Println("num : ", num)
	fmt.Println("pnum :", *pnum)
	//포인터 연산자를 이용한 값 변경
}

 

연산자 우선순위

 

순위 연산기호 연산자 결합방향
1
() 함수호출
[] 인덱스
-> 간접지정
++, -- 증가 및 감소
2
+, - 부호 연산(음수, 양수 표현)
! 논리 NOT
~ 비트 단위 NOT
(type) 타입 변환
* 간접 지정 연산
& 주소 연산
sizeof 바이트 단위 크기 계산
3 *, /, % 곱셈, 나눗셈 관련 연산
4 +, - 덧셈, 뺄셈

5 <<, >> 비트 이동
6 <, <=, >, => 대소 비교
7 ==, != 동등 비교
8 & 비트 AND
9 ^ 비트 XOR
10 | 비트 OR
11 && 논리 AND
12 || 논리 OR
13 ? : 조건 연산
14 =, +=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |= 대입 연산
15 , 콤마 연산

 

콘솔 입력 함수의 기본

fmt 패키지를 이용한 콘솔 입력 함수에는 Scanf, Scan, Scanln 등이 있지만 가장 많이 쓰는 건 Scanln 입니다.

 

Scanln은 여러 값을 동시에 입력받을 수 있습니다. 빈칸으로 값을 구분하고, 엔터를 입력하면 입력이 종료됩니다.

입력받는 변수에 &연산자를 붙여 입력 받고, 입력받을 변수는 미리 선언되어야 합니다.

package main

import "fmt"

func main() {
	var num1, num2, num3 int
	
	fmt.Print("정수 3개를 입력하세요 :")
	fmt.Scanln(&num1, &num2, &num3)
	fmt.Println(num1, num2, num3)
}

'Go' 카테고리의 다른 글

Go 기본 문법 4  (2) 2023.07.24
Go 기본 문법 3  (0) 2023.07.24
Go 기본 문법 2  (0) 2023.07.23
Go가 무엇인고  (0) 2023.07.11