Go의 fmt 패키지는 Printf, Sprintf, Fprintf 같은 함수에서 서식 지정자(format verb)를 사용해 값을 원하는 형태로 출력합니다.
그중 %v는 값을 타입에 맞는 기본 형식으로 출력하고, %q는 문자열이나 문자를 Go 리터럴 형태로 확인할 때 사용합니다.
%v: 값의 기본 형식 출력
%v는 전달된 값에 적합한 기본 형식을 선택해 출력합니다. 문자열, 정수, 실수, 불리언, 슬라이스, 구조체처럼 타입이 서로 다른 값을 같은 서식 지정자로 확인할 수 있습니다.
package main
import "fmt"
func main() {
productName := "keyboard"
stockQuantity := 12
discountRate := 0.15
available := true
fmt.Printf("상품명: %v\n", productName)
fmt.Printf("재고: %v\n", stockQuantity)
fmt.Printf("할인율: %v\n", discountRate)
fmt.Printf("판매 가능: %v\n", available)
}
출력:
상품명: keyboard
재고: 12
할인율: 0.15
판매 가능: true
%v는 타입별 서식 지정자를 구분하지 않아도 되므로 값 확인이나 디버깅에 편리합니다.
다만 출력 형식을 세밀하게 제어해야 할 때는 %d, %f, %s 같은 타입별 서식 지정자를 사용합니다.
package main
import "fmt"
func main() {
orderNumber := 7
totalAmount := 12500.5
customerName := "Daniel"
fmt.Printf("주문번호: %04d\n", orderNumber)
fmt.Printf("결제금액: %.2f\n", totalAmount)
fmt.Printf("고객명: %s\n", customerName)
}
출력:
주문번호: 0007
결제금액: 12500.50
고객명: Daniel
%v만 사용해도 값은 출력되지만, 다음과 같은 형식 제어는 타입별 서식 지정자가 더 적합합니다.
| 목적 | 서식 지정자 | 예시 |
|---|---|---|
| 정수 출력과 자릿수 지정 | %d |
%04d → 0007 |
| 실수의 소수점 자리 지정 | %f |
%.2f → 12500.50 |
| 문자열 출력 | %s |
Daniel |
| 타입에 맞는 기본 출력 | %v |
값의 기본 표현 |
구조체 출력
구조체에 %v를 사용하면 필드값이 선언된 순서대로 출력됩니다. %+v를 사용하면 필드 이름도 함께 출력됩니다.
package main
import "fmt"
type Product struct {
Name string
Price int
}
func main() {
product := Product{
Name: "keyboard",
Price: 45000,
}
fmt.Printf("%v\n", product)
fmt.Printf("%+v\n", product)
}
출력:
{keyboard 45000}
{Name:keyboard Price:45000}
구조체의 필드 이름과 값을 함께 확인하려면 %+v가 %v보다 읽기 쉽습니다.
%q: 따옴표와 이스케이프를 포함한 리터럴 형식 출력
문자열에 %q를 사용하면 큰따옴표로 감싸고, 줄바꿈이나 탭 같은 제어 문자를 이스케이프된 형태로 출력합니다.
package main
import "fmt"
func main() {
message := "hello\nworld"
fmt.Printf("%%s: %s\n", message)
fmt.Printf("%%q: %q\n", message)
}
출력:
%s: hello
world
%q: "hello\nworld"
%s는 줄바꿈 문자를 실제 줄바꿈으로 출력하지만, %q는 문자열에 들어 있는 \n을 눈으로 확인할 수 있도록 표시합니다.
따라서 %q는 단순히 따옴표만 붙이는 기능이라기보다, 값을 Go 문자열 리터럴과 유사한 형태로 표현하는 서식 지정자로 이해하는 것이 정확합니다.
빈 문자열, 공백, 탭, 줄바꿈 구분
%q를 사용하면 화면에서 구분하기 어려운 문자열을 명확히 확인할 수 있습니다.
package main
import "fmt"
func main() {
fmt.Printf("빈 문자열: %q\n", "")
fmt.Printf("공백 한 칸: %q\n", " ")
fmt.Printf("탭: %q\n", "\t")
fmt.Printf("줄바꿈: %q\n", "\n")
}
출력:
빈 문자열: ""
공백 한 칸: " "
탭: "\t"
줄바꿈: "\n"
Go의 string 타입은 null을 가지지 않습니다. 값이 지정되지 않은 문자열 변수에는 zero value인 빈 문자열 ""이 들어갑니다.
package main
import "fmt"
func main() {
var customerMemo string
fmt.Printf("%q\n", customerMemo)
}
출력:
""
%q가 nil이나 null을 빈 문자열로 변환한 것이 아닙니다. 원래 변수의 값이 빈 문자열이고, %q가 그 값을 따옴표로 감싸서 보여준 것입니다.
%q는 값 변환 기능이 아니라 출력 형식을 지정하는 기능입니다. 원본 변수의 값은 변경되지 않습니다.
문자와 정수에 %q 사용
%q는 문자열뿐 아니라 문자와 정수에도 사용할 수 있습니다. 정수에 사용하면 해당 Unicode 코드 포인트에 대응하는 문자를 작은따옴표로 출력합니다.
package main
import "fmt"
func main() {
fmt.Printf("문자열: %q\n", "Go")
fmt.Printf("문자: %q\n", '가')
fmt.Printf("정수 65: %q\n", 65)
fmt.Printf("바이트 슬라이스: %q\n", []byte("Go\n"))
}
출력:
문자열: "Go"
문자: '가'
정수 65: 'A'
바이트 슬라이스: "Go\n"
Go에서 작은따옴표로 작성한 '가'는 rune 값이며, rune은 int32의 별칭입니다. 따라서 %q는 정수값을 인용된 문자 형태로 출력할 수 있습니다.
%q와 맞지 않는 값
float64, 구조체, nil 포인터처럼 %q가 지원하는 형태와 맞지 않는 값을 전달하면 프로그램이 자동으로 빈 문자열을 출력하지 않습니다. 대신 fmt가 서식 지정자와 값의 타입이 맞지 않는다는 진단 문자열을 출력합니다.
package main
import "fmt"
func main() {
var value any
var name *string
fmt.Printf("%q\n", 3.14)
fmt.Printf("%q\n", value)
fmt.Printf("%q\n", name)
}
출력:
%!q(float64=3.14)
%!q(<nil>)
%!q(*string=<nil>)
이러한 출력은 정상적인 데이터 표현이 아니라, 잘못된 서식 지정자 사용을 알려주는 진단 결과입니다.
%v와 %q 선택 기준
| 상황 | 권장 서식 지정자 |
|---|---|
| 타입과 관계없이 값을 기본 형태로 확인 | %v |
| 구조체의 필드 이름과 값 확인 | %+v |
| 문자열 내용을 그대로 출력 | %s |
| 빈 문자열, 공백, 탭, 줄바꿈 구분 | %q |
| 정수의 자릿수나 진법 제어 | %d, %x, %b 등 |
| 실수의 소수점 자리 제어 | %f, %e, %g 등 |
다음 예제는 %s, %v, %q의 차이를 한 번에 보여줍니다.
package main
import "fmt"
func main() {
statusMessage := "ready\n"
fmt.Printf("%%s = [%s]\n", statusMessage)
fmt.Printf("%%v = [%v]\n", statusMessage)
fmt.Printf("%%q = %q\n", statusMessage)
}
출력:
%s = [ready
]
%v = [ready
]
%q = "ready\n"
문자열에 대해서는 %s와 %v의 결과가 대부분 같지만, %q는 문자열의 경계와 제어 문자를 확인할 수 있다는 차이가 있습니다.
정리
%v는 전달된 값을 타입에 맞는 기본 형식으로 출력합니다. 여러 타입의 값을 빠르게 확인하거나 구조체를 디버깅할 때 편리합니다.
%q는 문자열을 큰따옴표로, 문자를 작은따옴표로 감싸고 필요한 문자를 이스케이프해 출력합니다. 빈 문자열, 공백, 탭, 줄바꿈처럼 화면만 보고 구분하기 어려운 값을 확인할 때 유용합니다.
%v = 값의 기본 표현
%+v = 구조체 필드 이름을 포함한 기본 표현
%q = 인용 부호와 이스케이프를 포함한 리터럴 표현
단순한 값 확인에는 %v를 사용할 수 있지만, 출력 형식의 의도를 명확히 하거나 자릿수와 소수점 등을 제어해야 한다면 %s, %d, %f 같은 타입별 서식 지정자를 사용하는 것이 적절합니다.
참고 자료
- Go 공식
fmt패키지 문서: https://pkg.go.dev/fmt - Go 공식
fmt패키지 소스 문서: [https://go.dev/src/fmt/doc.go](https://go.dev/src/fmt/doc.go
'프로그래밍 > Go' 카테고리의 다른 글
| Go 배열, slice, map, range (0) | 2026.07.13 |
|---|---|
| Go if, for, switch와 break, continue (0) | 2026.07.11 |
| Go 리터럴, 변수, 상수와 Zero Value (0) | 2026.07.10 |
| Go package main과 패키지 구조 이해하기 (0) | 2026.07.10 |
| Ubuntu 24.04에서 Go 1.26.1과 VS Code 설치하기 (1) | 2026.07.03 |
댓글