Go

Go 기본 문법 2

알맹리 2023. 7. 23. 23:49

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

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

 

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

 

3. 자료형

자료형의 종류와 특징

Go 언어는 := 용법을 활용한 자료형 추론이 가능합니다. 정수는 int, 실수는 float32로 자동 할당됩니다.

 

// 자료형 크기 확인
import "unsafe" 
unsafe.Sizeof(변수)

 Boolean 타입

Go에서는 true, false만 사용합니다.

자료형 선언 크기(byte)
부울린 bool 1

 

정수 타입

uintptr 타입은 포인터의 비트 패턴을 할당할만한 크기의 자료형입니다. 포인터의 주소를 할당할 때 사용합니다.

자료형 뒤의 숫자는 비트를 의미합니다.

앞에 un 이 붙은 자료형은 0과 양의 정수만 표현합니다.

자료형 선언 크기(byte)
정수형(음수포함)
int n비트 시스템에서 n비트
int8 1
int16 2
int32 4
int64 8
정수형(0, 양수)
uint n비트 시스템에서 n비트
uint8 1
uint16 2
uint32 4
uint64 8
uintptr 8

int와 uint는 최소 4바이트 크기의 데이터 타입으로, 32비트 시스템에서는 4바이트, 64비트 시스템에서는 8바이트입니다.

 

실수 및 복소수 타입

자료형 선언 크기(byte)
실수
float32 4
float64 8
복소수
complex64 8
complex128 16

 

문자열 타입

문자열은 ""처럼 비어있을 수 있습니다. string으로 선언한 문자열 타입은 값을 변경할 수 없습니다.

자료형 선언 크기(byte)
문자열 string 16

 

기타 타입

byte는 uint8과 같은 자료형으로, 바이트 값을 8비트 부호 없는 정수 값과 구분하는 데 사용합니다.

rune은 int32와 같은 자료형으로, 관례상 문자 값을 정수 값과 구별하기 위해 사용합니다.

자료형 선언 크기(byte)
정수(0, 양수) byte 1
정수 rune 4

 

문자열 표현

  • Back Quote(`문자열`): 백쿼트로 둘러싸인 문자열은 Raw String Literal이라고 부릅니다. 이 안에 있는 값은 어느 기호든 문자열 자체로 인식되는 Raw String입니다. \n도 백쿼트 안에 있다면 문자 그대로 출력됩니다.
  • 이중인용부호("문자열"): Interpreterd String Literal이라고 부르니다. 이 안에 있는 이스케이프 시퀀스같은 문자열은 특별한 의미로 해석돼 그 기능을 수행합니다. 이중인용부호를 사용하면 여러 줄에 걸쳐 쓸 수 없습니다.

위 두 가지 방법 모두 + 연산자를 이용해 결합해 표현할 수 있습니다.

package main
import "fmt"

func main() {
	var rawLiteral string = `바로 실행해보면서 배우는 \n Golang`
    var interLiteral string = "바로 실행해보면서 배우는 \n Golang"
    
    plusString := "구름 " + "EDU\n" + "Golang"
    
    fmt.Println(rawLiteral)
    fmt.Println()
    fmt.Println(interLiteral)
    fmt.Println()
    fmt.Println(plusString)
}

 

자료형 변환

  • 자동(묵시적) 형 변환: 자동으로 발생하는 형 변환
  • 강제(명시적) 형 변환: 프로그래머가 형 변환을 명시해서 강제로 변환이 일어나게 하는 것

Go에서는 형 변환을 할 때 명시적으로 지정해주어야 합니다. 명시적인 지정이 없다면 런타임 에러가 발생합니다.

package main
import "fmt"

func main() {
	var num int = 10
    var changef float32 = float32(num) // int -> float32
    changei := int8(num) // int -> int8
    
    var str string = "goorm"
    changestr := []byte(str) // 바이트 배열
    str2 := string(changestr) // 바이트 배열을 문자열로 변환
    
    fmt.Println(num)
    fmt.Println(changef, changei)
    
    fmt.Println(str)
    fmt.Println(changestr)
    fmt.Println(str2)
}

 

아래처럼 연산식의 결괏값과 저장하려는 변수 자료형이 다르면 에러가 발생합니다.

num1, num2를 float32로 형변환 해야 합니다.

package main

import "fmt"

func main() {
	var num1, num2 int = 3, 4
	
	var result float32 = num1 / num2	
	
	fmt.Printf("%f", result)
}

 

4. 콘솔 출력과 입력 함수

콘솔 출력 함수(Print)

fmt 패키지에서 콘솔 출력 함수는 Println, Print, Printf 외에도 파일 출력을 위한 Fprintln, Fprint, Fprintf와 string 형으로 변환되는 Sprintln, Sprint, Sprintf가 있습니다.

 

코드 상단에 import "fmt"를 선언함으로써 fmt 패키지를 사용할 수 있습니다.

 

Println, Print

선언 출력 형태
Println 개행 자동 추가
Print 개행 자동 추가하지 않음
Printf 포멧 지정자를 이용하여 개발자가 원하는 형태로 출력

Println, Print 두 함수는 하나의 인자를 출력할 수도 있고, 여러 개의 인자를 콤마로 결합해 열거할 수 있다는 공통점이 있습니다.

 

Printf

반드시 포맷을 지정해줘야 합니다. a := 5일 때 fmt.Printf(a)로 출력할 수 없습니다.

배열을 한 번에 출력 가능합니다. 

Print와 마찬가지로 자동으로 개행되지 않습니다.

 

서식문자

 

Go에서는 %v를 통해 변수의 타입에 관계없이 출력할 수 있습니다.

%p는 값이 참조하는 주소값을 반환하는 서식문자입니다.

  • 출력 폭 지정: "%(폭)d"
  • 출력 폭에 0 채워 넣기: "%0(폭)d"
  • 왼쪽부터 출력: "%-(폭)d"
  • 소수점 이하 자리 지정: "%.(자릿수)f"
서식문자 출력 형태
%t bool
%b 2진수 정수
%c 문자
%d 10진수 정수
%o 8진수 정수
%x 16진수 정수, 소문자
%X 16진수 정수, 대문자
%f 10진수 방식의 고정 소수점 실수
%F 10진수 방식의 고정 소수점 실수
%e 지수 표현 실수, e
%E 지수 표현 실수, E
%g 간단한 10진수 실수
%G 간단한 10진수 실수
%s 문자열
%p 포인터
%U 유니코드
%T 타입
%v 모든 형식
%#v #을 이용해구분할 수 있는 형식 표현

 

package main

import "fmt"

func main() {
	fmt.Printf("5>6=%b\n", 5 > 6)
	fmt.Printf("15는 2진수로 %b\n", 15)
	fmt.Printf("저의 성은 %c 입니다\n", '김')
	fmt.Printf("19는 10진수로 %d입니다.\n", 19)
	fmt.Printf("19는 8진수로 %o입니다.\n", 19)
	fmt.Printf("19는 16진수로 %x입니다.\n", 19)
	fmt.Printf("19는 16진수로 %X입니다.\n", 19)
	fmt.Printf("19.1234는 고정 소수점으로 %f입니다.\n", 19.1234)
	fmt.Printf("19.1234는 고정 소수점으로 %F입니다.\n", 19.1234)
	fmt.Printf("19.1234의 지수 표현은 %e입니다.\n", 19.1234)
	fmt.Printf("19.1234의 지수 표현은 %E입니다.\n", 19.1234)
	fmt.Printf("19.1234의 간단한 실수 표현은 %g입니다.\n", 19.1234) // 고정 소수점이 아님
	fmt.Printf("19.1234의 간단한 실수 표현은 %G입니다.\n", 19.1234) // 고정 소수점이 아님
	fmt.Printf("문자열: %s\n", "안녕하세요.")

	var num int = 50
	fmt.Printf("num은 %d입니다.\n", num)

	fmt.Printf("num의 메모리 주소 출력: %p\n", &num) //주솟값을 참조하기 위해 &를 쓴다.
	fmt.Printf("num의 유니코드 값은 %U입니다.\n", num)
	fmt.Printf("num의 타입은 %T입니다.\n", num)
	fmt.Printf("num의 타입은 %T입니다.\n", num)
	fmt.Printf("모든 형식으로 출력: %v, %v\n", 54.234, "Hello")
	fmt.Printf("num의 타입은 %T입니다.\n", num)
	fmt.Printf("7이 어떤 형식인지 표시: %d, %#o, %#x\n", 7, 7, 7) //8진수는 앞에 0이 붙고, 16진수는 0x가 붙습니다.
	fmt.Printf("네 칸 차지하는 13: %4d\n", 13)
	fmt.Printf("빈칸은 0으로 채우고 4칸 차지하는 13: %04d\n", 13)
	fmt.Printf("총 네 칸 차지하고 왼쪽으로 정렬되는 13과 15: %-4d%-4d\n", 13, 15)
	fmt.Printf("12.1234를 소수점 둘째 자리까지만 표시하면 %.2f입니다.\n", 12.1234)

}

 

콘솔 입력 함수(Scan)

선언 입력 형태
Scanln 공백으로 구분하여 입력
Scan 공백과 개행으로 구분하여 입력
Scanf 포멧 지정자를 이용하여 개발자가 원하는 형태로 입력

Scanln 함수는 공백으로 입력 값을 구분하기 때문에 개행(엔터)하면 입력이 완료된다는 것을 의미합니다.

Scan 함수는 개행을 입력(엔터)하는 것 또한 데이터를 구분하는 입력 방식으로 인식합니다. 

 

package main

import "fmt"

func main() {
	var name string
	var gen string
	var school string
	
	fmt.Print("이름, 성별, 학교를 입력하세요.")
	fmt.Scanln(&name, &gen, &school)

	fmt.Println("이름은 ", name, " 성별은 ", gen, "학교는", school)
}
package main

import "fmt"

func main() {
	var name string
	var gen string
	var school string

	fmt.Print("이름, 성별, 학교를 입력하세요.")
	fmt.Scan(&name, &gen, &school)

	fmt.Println("이름은 ", name, " 성별은 ", gen, "학교는", school)
}

Scan함수로 값을 입력 받을 때 엔터로 각 값을 구분합니다.

package main

import "fmt"

func main() {
	var i, j int

	fmt.Print("주민등록번호를 -를 이용해 입력하세요 :")
	fmt.Scanf("%d-%d", &i, &j)

	fmt.Printf("주민등록번호는 %d-%d\n", i, j)
	fmt.Println("앞자리는", i)
	fmt.Println("뒷자리는", j)
}

Scanf 함수를 이용해 미리 지정한 포맷에 따라 입력받을 수 있습니다.

 

5. 반복문

Go는 while문이 없습니다.

// Go언어에서 for문의 형태
for 초기식; 조건식; 조건 변화식 {
	반복 수행할 구문
}

 

초기식, 조건식, 조건 변화식이 모두 포함된 for문

package main
 
import "fmt"
 
func main() {
	sum := 0
	
	for i := 1; i <= 10; i++ {
		sum += i
	}
	fmt.Println("1부터 10까지 정수 합계:", sum)
}

 

조건식만 쓰는 for 루프

Go의 for문은 while문처럼 간결하게 표현이 가능합니다.

package main

import "fmt"

func main() {
	n := 2
	
	for n < 100 {
		fmt.Printf("count %d\n", n)
		
		n *= 2
	}
}

 

무한루프

while(1)과 같은 방법 대신 for { 같은 형식으로 입력하는 것으로 무한루프를 만들 수 있습니다.

무한루프를 빠져나오기 위해 ctrl + c 를 입력하면 됩니다.

package main

import "fmt"

func main() {
	for {
		fmt.Printf("무한루프입니다.\n")
	}
}

 

for range문

다른 언어의 foreach와 비슷한 문법으로, 컬렉션으로부터 한 요소씩 가져와 차례로 for문 블럭의 문장을 실행한다는 뜻입니다.

for range문은 for 인덱스, 요소값 := range 컬렉션이름 으로 for 루프를 구성합니다. 

for range문은 컬렉션의 모든 요소에 접근해 차례로 리턴할 때 사용합니다.

range 키워드 다음의 컬렉션으로부터 하나씩 요소를 반환해서 그 요소의 인덱스와 값을 for 키워드 다음의 2개의 변수에 각각 할당합니다. 

package main

import "fmt"

func main() {
	var arr [6]int = [6]int{1, 2, 3, 4, 5, 6}

	for index, num := range arr {
		fmt.Printf("arr[%d]의 값은 %d입니다.\n", index, num)
	}
}

인덱스와 값을 모두 받지 않고 한가지 값만 가져올 수도 있습니다.

  • "_, 요소값"
  • "인덱스"
//인덱스를 생략한 예시
package main

import "fmt"

func main() {
	var actors [4]string = [4]string{"정우성", "류준열", "박보검", "이정재"}

	for _, actor := range actors {
		fmt.Printf("제가 좋아하는 배우는 %s입니다.\n", actor)
	}
}
//요소값을 생략한 예시
package main

import "fmt"

func main() {
	var actors [4]string = [4]string{"정우성", "류준열", "박보검", "이정재"}

	for index := range actors {
		fmt.Printf("배우가 %d명 입장했습니다.\n", index+1)
	}
}

인덱스가 정수가 아닌 때에도 활용할 수 있습니다.

package main

import "fmt"

func main() {
	var fruits map[string]string = map[string]string{
		"apple":  "red",
		"banana": "yellow",
		"grape":  "purple",
	}

	for fruit, color := range fruits {
		fmt.Printf("%s의 색깔은 %s입니다.\n", fruit, color)
	}
}

 

6. 조건문

조건에 따른 실행과 흐름 분기

  • Go의 조건문의 조건식은 반드시 Boolean 형으로 표현돼야 합니다. 
  • 조건식의 괄호는 생략 가능하고, 생략하는 것을 권장합니다.
  • 조건문이 한 줄이더라도 중괄호는 필수로 입력해야 합니다. 꼭 조건 블럭 안에 넣어야 합니다.
  • 괄호의 시작과 else문은 같은 줄에 있어야 합니다. 조건문이 시작하는 첫 번째 줄에 블록 시작 브레이스({)를 입력해야 합니다. 
package main

import "fmt"

func main() {
	var num int
	
	fmt.Print("정수입력 :")
	fmt.Scan(&num)

	if num == 1 {
		fmt.Print("hello\n")
	} else if num == 2 {
		fmt.Print("world\n")
	} else {
		fmt.Print("worng number..\n")
	}
}

조건식에 간단한 문장을 실행 가능합니다. (Optional Statement)

package main

import "fmt"

func main() {
	var num int

	fmt.Print("정수입력 :")
	fmt.Scan(&num)

	if val := num * 2; val == 2 {
		fmt.Print("hello\n")
	} else if val := num * 3; val == 6 {
		fmt.Print("world\n")
	} else {
		fmt.Print("worng number..\n")
	}
}

 

package main

import "fmt"

func main() {
	var opt int
	var num1, num2, result float32

	fmt.Print("1.덧셈 2.뺄셈 3.곱셈 4.나눗셈 선택:")
	fmt.Scan(&opt)
	fmt.Print("두 개의 실수 입력:")
	fmt.Scan(&num1, &num2)

	if opt == 1 {
		result = num1 + num2
	} else if opt == 2 {
		result = num1 - num2
	} else if opt == 3 {
		result = num1 * num2
	} else if opt == 4 {
		result = num1 / num2
	}

	fmt.Printf("결과: %f\n", result)
}

'Go' 카테고리의 다른 글

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