Go언어 공부 시 참고하는 강의 영상입니다.
https://www.youtube.com/watch?v=XzR5EOEZz6Q&list=PLy-g2fnSzUTBHwuXkWQ834QHDZwLx6v6j&index=12
목차
표준 출력 함수
표준 입력 함수
대입 연산자 활용
표준 출력 함수
표준 출력 함수로 Print(), Println(), Printf() 3 가지가 있습니다.
순서대로 입력값을 출력, 입력 값들을 출력하고 개행, 서식에 맞도록 입력값들을 출력하는 기능을 가지고 있습니다.
예시 코드를 통하여 각 함수의 차이를 알아보겠습니다.
package main
import "fmt"
func main(){
a := 10
b := 20
c := 123456789.12345
fmt.Print("a:",a,"b",b)
fmt.Println("a:",a,"b:",b,"c:",c)
fmt.Printf("a:%d b:%d c:%f\n",a,b,c)
}
출력
a:10b:20a: 10 b :20 c: 1.2345678912345e+08
a:10 b:20 c:123456789.123450
각각 표준 출력 함수이기에 출력이 위와 같이 나오게 됩니다.
Print의 경우는 있는 그대로 입력값을 출력하기에 띄어쓰기가 없으면 없는 대로 출력됩니다. 줄 바꿈 표시도 없기에 Println의 출력이 같은 줄에 출력되고 있는 것을 볼 수 있습니다.
Println의 경우는 Print와 다르게 값들 사이에 공백을 주어 가독성이 좋으며 마지막에 줄 바꿈까지 실행합니다. 따라서 Printf의 출력이 아래줄에 출력되고 있는 것을 볼 수 있습니다.
Printf의 경우는 출력하는 string에 '%d', '%f' 등과 같은 서식에 맞추어 출력을 합니다. 따라서 Println에서 출력한 c의 경우 '%g'의 서식인 지수형식으로 출력된 반면 Printf에서는 '%f'라는 서식을 지정해 주었기에 실수형식으로 출력되었습니다.
Printf의 서식 중 몇 가지만 소개해드리겠습니다.
'%v' : 데이터 타입에 맞춰서 기본 형태로 출력합니다. 특정한 타입지정 없이 출력을 목표로 한다면 '%v'만 사용하여도 무관할 것 같습니다.
'%e' : 지수형태로 값을 출력합니다. int와 같은 정수 타입에는 사용할 수 없습니다.
'%g' : 값이 큰 실수의 경우 지수형태로, 값이 작은 실수의 경우 실수형태로 출력합니다. int와 같은 정수 타입에는 사용할 수 없습니다.
'%q' : 문자열을 특수문자 기능 없이 그대로 출력합니다. 예를 들어 test := "\n"이라고 선언한 test를 string 출력인 '%s'로 출력하면 \n의 역할인 줄 바꿈이 실행됩니다. '%q'로 출력하는 경우 \n이라는 string이 출력됩니다.
표준 입력 함수
표준 입력 함수로 Scan(), Scanln(), Scanf() 3 가지가 있습니다.
Scan의 경우 빈 값을 입력 시 인식하지 않고 입력을 받을 때까지 반복됩니다. 예를 들어 값을 입력하지 않고 enter를 누르면 빈 값이 입력되는 것이 아니기에 값을 입력하도록 기다리고 있습니다.
Scanln의 경우 빈 값을 입력 후 enter를 누르면 아무런 입력 없이 이전에 선언되어 있는 값을 그대로 가지고 있습니다.
Scanf의 경우 입력받을 서식을 정하여 입력을 받습니다. Printf에서 지정했던 서식처럼 '%d', '%f' 등을 사용하여 값을 받습니다. 하지만 변수를 선언할 때 이미 type을 지정하였기 때문에 서식 또 작성하여야 하는 번거로움이 있어 Scanln 혹은 Scan을 사용할 것 같습니다.
함수 예시
package main
import "fmt"
func main(){
var a int
var b int
fmt.Print("a와 b입력 : ")
n,err:=fmt.Scan(&a,&b)
if err!=nil{
fmt.Println(err)
}else {
fmt.Println(n,a,b)
}
}
입력 함수는 func Scan(a ...interface{}) (n int, err error)로 선언되어 있습니다 ....interface{}는 많은 인자를 받을 수 있다는 의미입니다. 변수가 한 개를 받을 수 있고 50개를 받을 수 있고 다양하게 받을 수 있기 때문에 이렇게 선언되어 있습니다.
출력은 n과 err를 반환하게 되는데 n은 입력받은 값의 개수를 의미하고 err는 error메시지를 의미합니다.
fmt.Scan( &a, &b)에서 &의 역할은 변수의 주소 값을 가져오는 역할로 &a는 a의 주소를 가져오게 되는 것이고 값을 입력하면 a의 주소에 입력받은 값을 대입하게 됩니다.
Buffer
위와 같은 방법으로 입력이 되면 입력된 값은 Buffer에 저장되어 있습니다.
Buffer에 저장해 두고 시스템이 읽기 시작하는데 변수의 타입과 다른 값이 읽히면 그 즉시 오류를 내보냅니다.
뒤의 값을 보지 않아도 이미 타입이 이상하기에 오류를 내보내고 멈춰버리는데 여기서 문제는 Buffer에 입력한 값이 남아있어서 다음 값을 입력하였을 때 남아있는 Buffer의 값을 읽는 문제가 생깁니다.
또한 표준 입력 함수를 여러 개 사용하는 경우 처음 입력을 통하여 Buffer에 값을 입력하고 다음 입력 함수에서는 입력을 받지 않는 문제도 발생합니다.
package main
import "fmt"
func main(){
var name1 string
var age1 int
var name2 string
fmt.Print("Enter your name and age: ")
fmt.Scan(&name1, &age1)
fmt.Printf("Scan - Name: %s\nAge: %d\n", name1, age1)
fmt.Scanln(&name2)
fmt.Printf("Scanln - Name: %s\n", name2)
}
예시 1 위의 코드를 실행하고 test 15test라고 입력을 하게 된다면 age1의 입력에서 15까지는 읽고 입력이 되지만 t의 경우 숫자가 아니기에 오류가 발생하여 넘어가게 됩니다. 이 경우 Buffer에는 est가 남아있어 name2를 입력받지 않고 est가 name2에 대입됩니다.
예시 2 위의 코드를 실행하고 입력을 하게 된다면 Buffer에 값이 가 저장되어 name1과 age1을 입력받고 name2를 입력받는 것이 아닌 한 번의 입력으로 name1 age1 name2를 입력하게 됩니다.
- test1 15 test2를 입력하는 경우 name1은 test1, age1은 15, name2는 test2가 입력됩니다.
- test1 15를 입력하는 경우 name1은 test1, age1은 15, name2는 빈 값이 입력됩니다.
따라서 오류가 났을 때 Buffer의 값을 비워주는 작업이 필요합니다.
Buffer 비우기
package main
import (
"bufio"
"fmt"
"os"
)
func main(){
stdin := bufio.NewReader(os.Stdin)
var name1 string
var age1 int
var name2 string
fmt.Print("Enter your name and age: ")
fmt.Scan(&name1, &age1)
fmt.Printf("Scan - Name: %s\nAge: %d\n", name1, age1)
stdin.ReadString('\n')
fmt.Scanln(&name2)
fmt.Printf("Scanln - Name: %s\n", name2)
}
Buffer 작업을 하기 위하여 필요한 package는 bufio와 os가 필요하여 import에 bufio와 os를 추가합니다.
bufio의 NewReader를 사용하는데 변수는 os의 스탠더드인풋인 Stdin을 입력합니다.
이후 표준 입력 함수를 통하여 입력을 받습니다.
Buffer를 비우는 문장은 stdin.ReadString('\n')입니다.
입력받은 Buffer를 \n을 만날 때까지 값을 읽으라는 의미로 Buffer의 값을 읽으면 값을 Buffer에서 지우게 됩니다.
위의 코드를 실행하게 되면 test1 15 test2를 입력하게 되더라도 name1에 test1, age1에 15를 입력하고 Buffer를 읽어 값을 날리기에 새로 입력을 받게 됩니다.
대입 연산자 활용
Go에서는 값을 대입할 때 아래와 같은 방법으로 여러 개의 값을 한 번에 대입할 수 있습니다.
var a int
var b int
var c int
a, b, c = 10, 20, 30
fmt.Print(a, b, c)
// 출력 : 10 20 30
위와 같이 선언하면 a에는 10, b에는 20이 선언되게 됩니다.
이러한 방법을 활용하여 변수의 값을 편하게 교환할 수 있습니다.
이전에 배운 언어에서는 값을 교환하려면 임시 값을 선언하여 값을 교환하여야 했습니다.
JavaScript 예시
let a = 3;
let b = 4;
let temp = 0;
temp = a;
a = b;
b = temp;
Go 언어에서는 대입 연산자의 특징?을 활용하여 변수의 값 교환을 편리하게 할 수 있습니다.
a, b := 10, 20
a, b = b, a
fmt.Print(a, b)
// 출력 : 20 10
임시 변수를 선언하지 않기에 코드가 짧아지고 직관적이라는 점에서 되게 편리한 방법이라고 생각되어 Go의 매력이라고 생각되었습니다.
'Go language' 카테고리의 다른 글
[Go] Go언어 배열 (정적, 동적, slice, append, range) (0) | 2023.08.23 |
---|---|
[Go] 상수 선언과 특징 (iota, 비트 플래그) (0) | 2023.08.22 |
[Go] Go 변수와 기본 문법 (문법의 특징) (0) | 2023.08.20 |
[Go] Go 기본 구조 설명 (build 설정) (0) | 2023.08.20 |
[Go] Go 개발 환경 준비 (gopls 오류) (0) | 2023.08.17 |