Golang中常用的打印函数有fmt.Print、fmt.Println和fmt.Printf,主要区别在于输出格式:Print不添加空格和换行,Println在参数间加空格并末尾换行,Printf支持格式化字符串并通过动词精确控制输出。

Golang在处理字符串格式化和打印输出方面,主要依赖于标准库中的
fmt
io.Writer
在Golang中,
fmt
fmt.Print
fmt.Print(a ...interface{}) (n int, err error)fmt.Println(a ...interface{}) (n int, err error)fmt.Printf(format string, a ...interface{}) (n int, err error)fmt.Sprint
立即学习“go语言免费学习笔记(深入)”;
fmt.Sprint(a ...interface{}) stringfmt.Sprintln(a ...interface{}) stringSprint
fmt.Sprintf(format string, a ...interface{}) stringPrintf
fmt.Fprint
fmt.Fprint(w io.Writer, a ...interface{}) (n int, err error)io.Writer
fmt.Fprintln(w io.Writer, a ...interface{}) (n int, err error)Fprint
fmt.Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)Printf
io.Writer
fmt.Errorf
fmt.Errorf(format string, a ...interface{}) errorSprintf
error
%w
这些函数构成了Go语言中灵活、强大的输出和字符串处理能力的基础。理解它们各自的用途和细微差别,对于编写清晰、可维护的Go代码至关重要。
说实话,刚接触Go的时候,我也被
Println
Printf
最基础的当然是
fmt.Print
package main
import "fmt"
func main() {
name := "Alice"
age := 30
fmt.Print("Name:", name, "Age:", age, "\n") // 输出: Name:AliceAge:30
}你看,
Name:
Alice
Alice
Age:
这时候,
fmt.Println
package main
import "fmt"
func main() {
name := "Bob"
age := 25
fmt.Println("Name:", name, "Age:", age) // 输出: Name: Bob Age: 25
}是不是舒服多了?一行一个输出,清清楚楚。我个人在快速调试时,
Println
而真正的“格式化大师”非
fmt.Printf
Printf
package main
import "fmt"
func main() {
pi := 3.14159
count := 123
fmt.Printf("Pi is approximately %.2f and count is %d.\n", pi, count)
// 输出: Pi is approximately 3.14 and count is 123.
}这里
%.2f
%d
总结一下,它们的主要区别在于:
本文档主要讲述的是Android数据格式解析对象JSON用法;JSON可以将Java对象转成json格式的字符串,可以将json字符串转换成Java。比XML更轻量级,Json使用起来比较轻便和简单。JSON数据格式,在Android中被广泛运用于客户端和服务器通信,在网络数据传输与解析时非常方便。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
0
Println
Printf
选择哪个,就看你具体想要什么样的输出效果了。
要说
fmt
最常用的几个动词,我们先来过一遍:
%v
%v
fmt.Printf("Default value: %v\n", 123) // 123
fmt.Printf("Default string: %v\n", "hello") // hello
type User struct { Name string }
u := User{"Goopher"}
fmt.Printf("Default struct: %v\n", u) // {Goopher}但
%v
%+v
fmt.Printf("Struct with fields: %+v\n", u) // {Name:Goopher}%#v
fmt.Printf("Go syntax: %#v\n", u) // main.User{Name:"Goopher"}%T
fmt.Printf("Type of u: %T\n", u) // main.User%T
fmt.Printf("Boolean: %t\n", true) // true%d
%b
%o
%x
%x
num := 255
fmt.Printf("Decimal: %d, Binary: %b, Octal: %o, Hex: %x/%X\n", num, num, num, num, num)
// Decimal: 255, Binary: 11111111, Octal: 377, Hex: ff/FF%f
%e
%e
%g
%g
%e
%f
val := 123.456
fmt.Printf("Float: %f, Scientific: %e, General: %g\n", val, val, val)
// Float: 123.456000, Scientific: 1.234560e+02, General: 123.456%s
%q
str := "hello world"
fmt.Printf("String: %s, Quoted: %q\n", str, str)
// String: hello world, Quoted: "hello world"%p
ptr := &num
fmt.Printf("Pointer address: %p\n", ptr) // 0xc0000140a8 (地址会变)除了这些基本动词,我们还可以通过宽度、精度和标志来进一步控制格式。
fmt.Printf("Right padded: %8d\n", 123) // " 123"
fmt.Printf("Left padded: %-8s\n", "Go") // "Go " (负号表示左对齐)
fmt.Printf("Zero padded: %08d\n", 123) // "00000123" (0表示用0填充).数字
fmt.Printf("Float precision: %.2f\n", 3.14159) // 3.14
fmt.Printf("String precision: %.5s\n", "Golang programming") // Golanfmt.Printf("Combined: %-10.4f\n", 12.34567) // "12.3457 "掌握这些格式化动词及其修饰符,你就能像个魔术师一样,让数据在控制台或任何输出流中以最优雅、最精确的方式呈现。这不仅仅是美观,更是提升代码可读性和调试效率的关键。
在我看来,Golang的字符串格式化能力在日志记录和错误处理这两个领域,简直是如鱼得水,发挥着举足轻重的作用。但要用得好,还得讲究一些“最佳实践”,避免一些坑,让我们的日志既清晰又便于分析,错误信息既准确又富有上下文。
日志记录:
日志是排查问题、监控系统运行状态的眼睛。格式化的日志能大大提升可读性和可分析性。
使用fmt.Sprintf
fmt.Printf
fmt.Sprintf
log
logrus
zap
package main
import (
"fmt"
"log"
)
func main() {
userID := 101
action := "login"
status := "success"
// 使用Sprintf构建日志消息
logMsg := fmt.Sprintf("User %d performed action '%s' with status: %s", userID, action, status)
log.Println(logMsg)
// 实际应用中,可能会进一步封装成JSON或发送给日志服务
// log.Printf("{\"user_id\": %d, \"action\": \"%s\", \"status\": \"%s\"}", userID, action, status)
}这样,日志库就能接收到已经格式化好的字符串,进行后续处理。
提供足够的上下文信息: 日志的价值在于提供“当时发生了什么”的线索。所以,在格式化日志时,不要吝啬添加关键信息,比如请求ID、用户ID、操作名称、相关参数等。但也要避免过度冗余,保持信息密度。
一致的日志格式: 无论是人工阅读还是机器解析,一致的日志格式都至关重要。定义好你的日志模板,并坚持使用。例如,总是以时间戳开头,接着是日志级别,然后是具体的事件描述。
错误处理:
Go语言的错误处理哲学是“显式”和“值传递”。
fmt.Errorf
使用fmt.Errorf
fmt.Errorf
Printf
package main
import (
"fmt"
"strconv"
)
func parseAndProcess(input string) (int, error) {
val, err := strconv.Atoi(input)
if err != nil {
// 在这里添加上下文:哪个输入导致了转换失败
return 0, fmt.Errorf("failed to parse input '%s' to integer: %v", input, err)
}
if val < 0 {
// 另一个上下文:值不符合业务规则
return 0, fmt.Errorf("input value %d is negative, expected non-negative", val)
}
return val * 2, nil
}
func main() {
if _, err := parseAndProcess("abc"); err != nil {
fmt.Println("Error:", err) // Error: failed to parse input 'abc' to integer: strconv.Atoi: parsing "abc": invalid syntax
}
if _, err := parseAndProcess("-5"); err != nil {
fmt.Println("Error:", err) // Error: input value -5 is negative, expected non-negative
}
}这样,当错误向上层传播时,上层函数就能获得足够的信息来判断问题出在哪里。
Go 1.13+ 的错误包装(%w
fmt.Errorf
%w
package main
import (
"errors"
"fmt"
"os"
)
func readFile(filename string) ([]byte, error) {
data, err := os.ReadFile(filename)
if err != nil {
// 使用%w包装原始错误,保留错误链
return nil, fmt.Errorf("failed to read file '%s': %w", filename, err)
}
return data, nil
}
func processFile(filename string) error {
_, err := readFile(filename)
if err != nil {
// 上层函数可以继续包装,或者直接返回
return fmt.Errorf("error processing file operation: %w", err)
}
return nil
}
func main() {
err := processFile("non_existent_file.txt")
if err != nil {
fmt.Println("Application error:", err)
// 可以使用errors.Is或errors.As来检查错误链中的特定错误
if errors.Is(err, os.ErrNotExist) {
fmt.Println("File does not exist!")
}
}
}%w
总的来说,无论是日志还是错误,核心思想都是“提供足够但不过载的信息”。通过
fmt.Sprintf
fmt.Errorf
以上就是Golang字符串格式化与打印输出方法的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号