Go 다양한 입출력

Go의 표준 입출력은 fmt 패키지를 사용한다. 

package main

import "fmt"

func main() {
	var num int
	fmt.Scan(&num)  // 입력
	fmt.Print(num)  // 출력
}

하지만 위와 같은 방식의 표준 입출력은 속도가 느리다. 만약 코딩 테스트를 푼다면 문제에 따라 시간 초과의 원인이 될 수도 있다.


bufio Reader를 이용한 빠른 입출력

import (
	"bufio"
	"fmt"
	"os"
)

var reader = bufio.NewReader(os.Stdin)
var writer = bufio.NewWriter(os.Stdout)

func main() {
	defer writer.Flush()

	var num int
	fmt.Fscan(reader, &num) // 입력
	fmt.Fprint(writer, num) // 출력
}

scan과 print 앞에 F를 붙여주게 되면 파일 입출력을 할 수 있게 된다. 하지만 파일 대신 os.Stdinos.Stdout를 사용해 표준 입출력을 할 수 있도록 한다. ReaderWriter는 버퍼를 이용해 입출력을 돕는 객체이다. Fscan과 Fprint에 첫 인자로 객체를 전달하는 것을 볼 수 있다. 또한 코드가 종료되기 전 writer를 Flush를 해주어야 한다. Flush는 버퍼에 저장된 데이터를 파일로 저장하는 것을 말하는데, 이 경우는 표준 출력을 뜻한다. 즉, Flush를 하지 않으면 출력이 되지 않는다. 

import (
	"bufio"
	"os"
	"strings"
)

var reader = bufio.NewReader(os.Stdin)

func main() {
	sentence, _ := reader.ReadString('\n')
	sentence = strings.TrimSpace(sentence)
}

만약 입력 시 공백을 포함해 문자열을 받아와야 한다면 ReadString('\n')을 사용할 수 있다. 줄바꿈이 발생하기 전까지 모든 값을 읽어오지만 변수에 저장된 값은 '\n'을 포함하고 있다. 따라서 TrimSpace를 통해 '\n'과 양 끝의 공백을 제거할 수 있다.

fmt.Fprint(writer, n)
fmt.Fprintln(writer, n)
fmt.Fprintf(writer, "%d", n)
  • Fprint: 별도의 처리 없이 값을 출력한다. 
  • Fprintln: 마지막에 '\n'이 추가된다. 
  • Fprintf: 포맷된 문자열 형식에 따라 출력한다. 

여기서 주의할 점은 Fprint가 항상 Print보다 빠른 것은 아니다. 출력하는 줄 수가 많은 경우 오히려 Print가 더 빠를 수 있다. 


Scanner를 이용한 문자열 입력

import (
	"bufio"
	"os"
)

var sc = bufio.NewScanner(os.Stdin)

func main() {
	sc.Scan()             // '\n'까지 한 줄을 읽음
	sentence := sc.Text() // 입력된 값을 변수에 저장
}

Scanner도 버퍼를 이용해 표준 입력을 할 수 있는 객체이다. Scan을 통해 한 줄을 읽어오고 Text를 이용해 버퍼의 값을 변수에 저장한다. ReadString('\n')과 달리 '\n'은 저장되지 않는다. 

 

여러 줄 읽어오기

import (
	"bufio"
	"fmt"
	"os"
)

var sc = bufio.NewScanner(os.Stdin)

func main() {
	inputs := make([]string, 0)
	for {
		sc.Scan()
		if input := sc.Text(); len(input) != 0 {
			inputs = append(inputs, input)
		} else {
			break
		}
	}
}

한 줄 씩 읽어와 Slice에 저장한다. 더 이상 읽어올 내용이 없다면 for문을 벗어나며 입력이 종료된다. 

 

읽어온 내용 공백으로 분리

import (
	"bufio"
	"os"
	"strings"
)

var sc = bufio.NewScanner(os.Stdin)

func main() {
	sc.Scan()
	input := sc.Text()
	inputArr := strings.Split(input, " ")
}

Split은 특정 문자열을 기준으로 분리된 배열을 반환한다. 위 코드의 경우, 공백을 기준으로 문자열을 분리해 반환한다.