서식 지정자 이해하기
Go는 다양한 데이터 타입을 출력할 때 사용할 수 있는 강력한 포맷팅 기능을 제공합니다. 이는 주로 fmt 패키지의 Printf 계열 함수와 함께 사용됩니다.
| 카테고리 | 서식 코드 | 설명 |
|---|---|---|
| 일반형 | %v | 값의 기본 형식으로 출력 |
| %+v | 구조체 필드 이름 포함하여 출력 | |
| %#v | Go 코드 형태로 값 표현 | |
| %T | 값의 타입 출력 | |
| %% | 퍼센트 기호(%) 자체를 출력 | |
| 불리언 | %t | bool 값(true/false) 출력 |
| 정수형 | %b | 2진수로 출력 |
| %c | 유니코드 코드 포인트에 해당하는 문자 출력 | |
| %d | 10진수 정수 출력 | |
| %o | 8진수 출력 | |
| %x | 16진수 소문자(a-f) 사용 | |
| %X | 16진수 대문자(A-F) 사용 | |
| %U | 유니코드 표기법 (예: U+4E00) | |
| 부동소수점 및 복소수 | %b | 이진 지수 표기 (예: -123p-4) |
| %e | 과학적 표기법, 소문자 e 사용 | |
| %E | 과학적 표기법, 대문자 E 사용 | |
| %f | 소수점 포함 일반 실수 형식 | |
| %F | %f와 동일 | |
| %g | %e 또는 %f 중 더 간결한 형식 자동 선택 | |
| %G | %E 또는 %F 중 더 간결한 형식 자동 선택 | |
| 문자열 및 바이트 슬라이스 | %s | 문자열 또는 []byte 직접 출력 |
| %q | 쌍따옴표로 감싸진 문자열 리터럴, 필요시 이스케이프 처리 | |
| %x | 각 바이트를 16진수 소문자로 출력 | |
| %X | 각 바이트를 16진수 대문자로 출력 | |
| 포인터 | %p | 메모리 주소를 16진수로 출력 (0x 접두사 포함) |
| 너비 및 정밀도 제어 | %f | 기본 너비, 기본 정밀도 |
| %9f | 총 너비 9, 기본 정밀도 | |
| %.2f | 기본 너비, 소수점 둘째 자리까지 | |
| %9.2f | 총 너비 9, 소수점 둘째 자리까지 | |
| %9.f | 총 너비 9, 소수점 없음 |
다음은 숫자 포맷팅 예제입니다:
value := 15.678
fmt.Printf("%f\n", value) // 출력: 15.678000
fmt.Printf("%9f\n", value) // 출력: 15.678000 (전체 너비 9)
fmt.Printf("%.2f\n", value) // 출력: 15.68 (반올림됨)
fmt.Printf("%9.2f\n", value) // 출력: 15.68 (공백 포함)
fmt.Printf("%9.f\n", value) // 출력: 16 (소수점 없음)
fmt 패키지 출력 함수 비교
Go의 fmt 패키지는 목적에 따라 여러 종류의 출력 함수를 제공하며, 다음과 같이 세 그룹으로 나눌 수 있습니다:
- Fprint 계열:
Fprint,Fprintf,Fprintln— 출력 대상으로io.Writer인터페이스를 받으며, 파일, 네트워크 연결 등 임의의 출력 스트림에 쓸 수 있음. - Sprint 계열:
Sprint,Sprintf,Sprintln— 결과를 문자열로 생성하여 반환함. 출력 대신 저장하거나 처리할 때 유용. - Print 계열:
Print,Printf,Println— 표준 출력(os.Stdout)에 직접 출력함. 내부적으로Fprint(os.Stdout, ...)를 호출함.
예를 들어, 다음 코드는 두 문자열을 조합하여 문자열을 생성합니다:
resultWithNewline := fmt.Sprintln("go.dev", 2024)
resultCompact := fmt.Sprint("go.dev", 2024)
// resultWithNewline = "go.dev 2024\n"
// resultCompact = "go.dev2024"
또한, Print 계열 함수들은 실제로 Fprint 계열 함수를 기반으로 구현되어 있으며, 다음과 같은 관계가 있습니다:
func Print(a ...interface{}) (n int, err error) {
return Fprint(os.Stdout, a...)
}
이러한 구조 덕분에 Go는 일관된 출력 메커니즘을 유지하면서도 다양한 사용 시나리오에 유연하게 대응할 수 있습니다.