向外输出
fmt包实现了类似C语言printf和scanf的格式化I/O。主要分为向外输出内容和获取输入内容两大部分。
内置输出
不需要引入标准库,方便
c
package main
func main() {
print("我是控制台打印,我不换行 可以自己控制换行 \n我是另一行")
println("Hello World")
}

fmt标准输出
Print系列函数会将内容输出到系统的标准输出,
区别在于Print函数直接输出内容,
Printf函数支持格式化输出字符串,
Println函数会在输出内容的结尾添加一个换行符。
go
package main
import "fmt"
type User struct {
Name string
Age int
}
fmt.Print("在终端打印该信息。")
name := "枯藤"
fmt.Printf("我是:%s\n", name)
user := User{"张三", 20}
fmt.Printf("我是一个字符串 %v", user)
fmt.Printf("我是一个字符串 %+v", user)
fmt.Println("在终端打印单独一行显示")

Fprint
Fprint系列函数会将内容输出到一个io.Writer接口类型的变量w中,我们通常用这个函数往文件中写入内容。
go
// 默认输出到控制台
fmt.Fprintf(os.Stdout, "hello world \n")
// 输出到标准错误
fmt.Fprintf(os.Stderr, "这是错误信息 \n")
//文件输出
file, _ := os.Create("output.txt")
fmt.Fprintf(file, "写入文件的内容111") // 输出到文件
file.Close()
// 输出到内存缓冲区
var buf bytes.Buffer
fmt.Fprintf(&buf, "写入缓冲的内容")
// 输出到网络连接
conn, _ := net.Dial("tcp", "example.com:80")
fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
//Fprintf简写,默认输出到控制台
fmt.Print("我是文本内容")

Sprint
Sprint系列函数会把传入的数据生成并返回一个字符串。
该放大的接口定义
go
func Sprint(a ...interface{}) string
func Sprintf(format string, a ...interface{}) string
func Sprintln(a ...interface{}) string
go
s1 := fmt.Sprint("三体即将到来")
name := "三体"
age := 18
s2 := fmt.Sprintf("name:%s,age:%d", name, age)
s3 := fmt.Sprintln("三体")
fmt.Println(s1, s2, s3)

Errorf
Errorf函数根据format参数生成格式化字符串并返回一个包含该字符串的错误。
go
func Errorf(format string, a ...interface{}) error
通常使用这种方式来自定义错误类型,例如:
go
err := fmt.Errorf("这是一个错误")
fmt.Println(err)
打印:
这是一个错误
格式化占位符

go
fmt.Printf("%v\n", 100)
fmt.Printf("%v\n", false)
o := struct {
name string
age int
}{"枯藤", 18}
fmt.Printf("%v\n", o)
fmt.Printf("%+v\n", o)
fmt.Printf("%#v\n", o)
fmt.Printf("%T\n", o)
fmt.Printf("100%%\n")


go
isFlag := false
n := 65
fmt.Printf("%b\n", n)
fmt.Printf("%c\n", n)
fmt.Printf("%d\n", n)
fmt.Printf("%o\n", n)
fmt.Printf("%x\n", n)
fmt.Printf("%X\n", n)
go
func main() {
s := "枯藤"
fmt.Printf("%s\n", s)
fmt.Printf("%q\n", s)
fmt.Printf("%x\n", s)
fmt.Printf("%X\n", s)
}


go
a := 18
fmt.Printf("%p\n", &a)
fmt.Printf("%#p\n", &a)


go
n := 88.99
fmt.Printf("%f\n", n)
fmt.Printf("%10f\n", n)
fmt.Printf("%.2f\n", n)
fmt.Printf("%10.2f\n", n)
fmt.Printf("%10.f\n", n)

获取输入
Go语言fmt包下有f
mt.Scan、
fmt.Scanf、
fmt.Scanln
三个函数,可以在程序运行过程中从标准输入获取用户的输入。
go
func main() {
var (
name string
age int
married bool
)
fmt.Scan(&name, &age, &married)
fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)
}

Time 时间
时间和日期是我们编程中经常会用到的,本文主要介绍了Go语言内置的time包的基本用法。
时间类型
go
now := time.Now() //获取当前时间
fmt.Printf("current time:%v\n", now)
year := now.Year() //年
month := now.Month() //月
day := now.Day() //日
hour := now.Hour() //小时
minute := now.Minute() //分钟
second := now.Second() //秒
fmt.Printf("年:%d\n", year)
fmt.Printf("月:%d\n", month)
fmt.Printf("日:%d\n", day)
fmt.Printf("时:%d\n", hour)
fmt.Printf("分:%d\n", minute)
fmt.Printf("秒:%d\n", second)
fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)

时间戳
时间戳是自1970年1月1日(08:00:00GMT)至当前时间的总毫秒数。它也被称为Unix时间戳(UnixTimestamp)。
在Go语言中,时间戳的单位关系如下:
标准时间戳(Unix时间戳)是以秒为单位的整数
1秒 = 1000毫秒
1秒 = 1,000,000,000纳秒(10亿纳秒)
go
now := time.Now() //获取当前时间
timestamp1 := now.Unix() //时间戳
timestamp2 := now.UnixMilli()
timestamp3 := now.UnixMicro()
timestamp4 := now.UnixNano() //纳秒时间戳
fmt.Printf(" 时间戳:%v\n", timestamp1)
fmt.Printf("毫秒时间戳:%v\n", timestamp2)
fmt.Printf("微秒时间戳:%v\n", timestamp3)
fmt.Printf("纳秒时间戳:%v\n", timestamp4)

时间操作
Add求时间间隔
我们在日常的编码过程中可能会遇到要求时间+时间间隔的需求,Go语言的时间对象有提供Add方法如下:
go
now := time.Now()
fmt.Println(now)
//later := now.Add(time.Hour) // 当前时间加1小时后的时间
//一秒后
second := now.Add(time.Second)
//一分钟后
minute := now.Add(time.Minute)
//一小时后
hour := now.Add(time.Hour)
//一天后
day := now.Add(24 * time.Hour)
//一周后
week := now.Add(7 * 24 * time.Hour)
//一个月后
month := now.Add(30 * 24 * time.Hour)
//一年后
year := now.Add(365 * 24 * time.Hour)
//一秒钟前
preSecond := now.Add(-time.Second)
//一分钟前
preMinute := now.Add(-time.Minute)
//一小时前
preHour := now.Add(-time.Hour)
//一天前
preDay := now.Add(-24 * time.Hour)
//一周前
preWeek := now.Add(-7 * 24 * time.Hour)
//一个月前
preMonth := now.Add(-30 * 24 * time.Hour)
//一年前
preYear := now.Add(-365 * 24 * time.Hour)
fmt.Printf("一秒后 %v\n", second)
fmt.Printf("一分钟后 %v\n", minute)
fmt.Printf("一小时后 %v\n", hour)
fmt.Printf("一天后 %v\n", day)
fmt.Printf("一周后 %v\n", week)
fmt.Printf("一个月后 %v\n", month)
fmt.Printf("一年后 %v\n", year)
fmt.Println("=======================")
fmt.Printf("一秒钟前 %v\n", preSecond)
fmt.Printf("一分钟前 %v\n", preMinute)
fmt.Printf("一小时前 %v\n", preHour)
fmt.Printf("一天前 %v\n", preDay)
fmt.Printf("一周前 %v\n", preWeek)
fmt.Printf("一个月前 %v\n", preMonth)
fmt.Printf("一年前 %v\n", preYear)

Sub 求两个时间之间的差值
go
now := time.Now()
fmt.Println("开始时间:", now)
// 正确用法:需要一个另一个时间对象来调用Sub
later := time.Now()
fmt.Println("时间差:", later.Sub(now).Seconds(), "s")
fmt.Println("毫秒差:", later.Sub(now).Milliseconds(), "ms")
fmt.Println("微秒差:", later.Sub(now).Microseconds(), "us")
fmt.Println("纳秒差:", later.Sub(now).Nanoseconds(), "ns")
fmt.Println("结束时间:", later)
go
开始时间: 2025-08-06 16:10:08.6476536 +0800 CST m=+0.002114101
时间差: 0.0113969 s
毫秒差: 11 ms
微秒差: 11396 us
纳秒差: 11396900 ns
结束时间: 2025-08-06 16:10:08.6590505 +0800 CST m=+0.013511001
Equal 两个时间是否相等
go
now := time.Now()
fmt.Println("开始时间:", now)
//Equal 两个时间是否相等
now1 := time.Now()
now2 := time.Now()
fmt.Println("now1 == now2:", now1.Equal(now2))
//Add 增加时间
now3 := now.Add(time.Second)
fmt.Println("now1 == now3:", now1.Equal(now3))
fmt.Println(now3)

Before
如果t代表的时间点在u之前,返回真;否则返回假。
go
func (t Time) Before(u Time) bool
go
func main() {
now := time.Now()
future := now.Add(5 * time.Second) // 当前时间加5秒
past := now.Add(-5 * time.Second) // 当前时间减5秒
// 比较时间先后
fmt.Println("now在future之前?", now.Before(future)) // true
fmt.Println("now在past之前?", now.Before(past)) // false
fmt.Println("future在now之前?", future.Before(now)) // false
}
go
now在future之前? true
now在past之前? false
future在now之前? false
注意事项
- 比较时会考虑时区信息
- 对于相同的时间点,Before() 会返回 false
- 通常与 After() 和 Equal() 方法配合使用
- 你的原始代码中
now.Before(now.Add(1 * time.Second))
总是返回true
,因为now.Add(1 * time.Second)
确实是比now
晚1秒的时间。
After
与Before相反 如果t代表的时间点在u之后,返回真;否则返回假。
go
func (t Time) After(u Time) bool
go
now := time.Now()
future := now.Add(5 * time.Second) // 当前时间加5秒
past := now.Add(-5 * time.Second) // 当前时间减5秒
// 比较时间先后
fmt.Println("now在future之后?", now.After(future)) // false
fmt.Println("now在past之后?", now.After(past)) // true
fmt.Println("future在now之后?", future.After(now)) // true
go
now在future之后? false
now在past之后? true
future在now之后? true
实际场景的应用
- 检查任务是否超时
go
deadline := time.Now().Add(2 * time.Second)
time.Sleep(3 * time.Second)
// ... 执行一些耗时操作 ...
if time.Now().After(deadline) {
fmt.Println("任务已超时")
return
}
fmt.Println("任务已完成")
go
任务已超时
- 验证证书有效期
go
expiryDate := time.Date(2023, 12, 31, 0, 0, 0, 0, time.UTC)
if time.Now().After(expiryDate) {
fmt.Println("证书已过期")
} else {
fmt.Println("证书仍在有效期内")
}
go
证书已过期
- 定时器检查
go
在这里插入代码片
go
func main() {
lastCheck := time.Now()
nextCheck := lastCheck.Add(3 * time.Second)
time.Sleep(4 * time.Second)
if time.Now().After(nextCheck) {
fmt.Println("需要执行定期检查了")
// 执行检查逻辑...
}
}
go
需要执行定期检查了
- 与Before配合使用
go
startTime := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
endTime := time.Date(2025, 9, 2, 0, 0, 0, 0, time.UTC)
current := time.Now()
if current.After(startTime) && current.Before(endTime) {
fmt.Println("当前在时间范围内")
}
go
当前在时间范围内
定时器
使用time.Tick(时间间隔)来设置定时器,定时器的本质上是一个通道(channel)。
go
ticker := time.Tick(time.Second) //定义一个1秒间隔的定时器
for i := range ticker {
fmt.Println(i) //每秒都会执行的任务
}
go
2025-08-06 16:36:18.7846155 +0800 CST m=+1.001458901
2025-08-06 16:36:19.7977679 +0800 CST m=+2.014611301
2025-08-06 16:36:20.7935061 +0800 CST m=+3.010349501
2025-08-06 16:36:21.7993051 +0800 CST m=+4.016148501
2025-08-06 16:36:22.7938337 +0800 CST m=+5.010677101
2025-08-06 16:36:23.7972015 +0800 CST m=+6.014044901
2025-08-06 16:36:24.7889924 +0800 CST m=+7.005835801
时间格式化
- 时间类型有一个自带的方法Format进行格式化
- Go的诞生时间2006年1月2号15点04分(记忆口诀为2006 1 2 3 4)
go
now := time.Now()
// 格式化的模板为Go的出生时间2006年1月2号15点04分 Mon Jan
// 24小时制
fmt.Println(now.Format("2006-01-02 15:04:05.000 Mon Jan"))
// 12小时制
fmt.Println(now.Format("2006-01-02 03:04:05.000 PM Mon Jan"))
fmt.Println(now.Format("2006/01/02 15:04"))
fmt.Println(now.Format("15:04 2006/01/02"))
fmt.Println(now.Format("2006/01/02"))
go
2025-08-06 16:39:19.865 Wed Aug
2025-08-06 04:39:19.865 PM Wed Aug
2025/08/06 16:39
16:39 2025/08/06
2025/08/06
解析字符串格式的时间
go
now := time.Now()
fmt.Println(now)
// 加载时区
loc, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
fmt.Println(err)
return
}
// 按照指定时区和指定格式解析字符串时间
timeObj, err := time.ParseInLocation("2006/01/02 15:04:05", "2019/08/04 14:15:20", loc)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(timeObj)
fmt.Println(timeObj.Sub(now))
go
2025-08-06 16:42:04.4364547 +0800 CST m=+0.001074101
2019-08-04 14:15:20 +0800 CST
-52658h26m44.4364547s
Flag命令行
Go语言内置的flag包实现了命令行参数的解析,flag包使得开发命令行工具更为简单。
flag包基本使用
导入包
go
import flag
flag参数类型
实例1
go
var name string
var age int
var married bool
var delay time.Duration
flag.StringVar(&name, "name", "张三", "姓名")
flag.IntVar(&age, "age", 18, "年龄")
flag.BoolVar(&married, "married", false, "婚否")
flag.DurationVar(&delay, "d", 0, "时间间隔")
// 添加这行代码来解析命令行参数
flag.Parse()
// 打印解析后的参数值
fmt.Printf("姓名: %s\n年龄: %d\n婚否: %t\n时间间隔: %v\n", name, age, married, delay)
go
PS E:\work\code\go\demo> go run main.go -name 李四 -age 25 -married=true -d 1h30m
姓名: 李四
年龄: 25
婚否: true
时间间隔: 1h30m0s
PS E:\work\code\go\demo> go run main.go
姓名: 张三
年龄: 18
婚否: false
时间间隔: 0s
实例2
go
package main
import (
"flag"
"fmt"
"time"
)
type User struct {
Name string
Age int
}
func main() {
//定义命令行参数方式1
var name string
var age int
var married bool
var delay time.Duration
flag.StringVar(&name, "name", "张三", "姓名")
flag.IntVar(&age, "age", 18, "年龄")
flag.BoolVar(&married, "married", false, "婚否")
flag.DurationVar(&delay, "d", 0, "延迟的时间间隔")
//解析命令行参数
flag.Parse()
fmt.Println(name, age, married, delay)
//返回命令行参数后的其他参数 []数组,如果你写了没有定义的参数,就会出现这里
fmt.Println(flag.Args())
//返回命令行参数后的其他参数个数,如果你写了没有定义的参数,就会统计个数在这里
fmt.Println(flag.NArg())
//返回使用的命令行参数个数
fmt.Println(flag.NFlag())
}
命令1,借助help来查看该命令需要什么参数
go
go run main.go --help

命令2,使用默认参数
go
go run main.go

命令2,填写所需要的参数
错误写法
go
go run main.go -age 800 -d 22m -married true -name 李白
**返回命令行参数后的其他参数 []数组,如果你写了没有定义的参数,就会出现这里**
fmt.Println(flag.Args())
**返回命令行参数后的其他参数个数,如果你写了没有定义的参数,就会统计个数在这里**
fmt.Println(flag.NArg())

问题原因
-
当你使用 -married true 时:
flag包期望布尔标志后面不跟参数值
true被当作一个独立参数处理
-name和"李白"也被当作独立参数
-
当前解析结果:
-age、-d 被正确解析
-married 被解析为true,但后面的true被当作额外参数
-name 李白 整个被当作额外参数,没有被正确解析
-married后面不能跟true ,如果想填写李白已婚则
go
go run main.go -age 800 -d 22m -married -name 李白
李白未婚
则 直接取掉-married
go
go run main.go -age 800 -d 22m -name 李白
OS
更详细的OS 请看链接
添加链接描述
- Getwd 获取当前工作目录
c
package main
import (
"os"
)
func main() {
dir, err := os.Getwd()
if err != nil {
panic(err)
}
println(dir)
}
c
E:\work\code\go\demo
- 创建文件
c
package main
import "os"
func main() {
// 创建文件
create, err := os.Create("readme.md")
if err != nil {
panic(err)
}
defer create.Close()
}
底层源码,其实是调用了一个OpenFile方法,并且默认的权限是0666
Log日志
常规使用
Go语言内置的log包实现了简单的日志服务。本文介绍了标准库log的基本使用。
log包定义了Logger类型,该类型提供了一些格式化输出的方法。
本包也提供了一个预定义的"标准"logger,
可以通过调用函数
Print系列(Print|Printf|Println)、 Fatal系列(Fatal|Fatalf|Fatalln)、 Panic系列(Panic|Panicf|Panicln)
来使用,比自行创建一个logger对象更容易使用。
使用Logger
go
log.Println("这是一条很普通的日志。")
v := "很普通的"
log.Printf("这是一条%s日志。\n", v)
log.Fatalln("这是一条会触发fatal的日志。")
log.Panicln("这是一条会触发panic的日志。")

配置logger
1 flag选项
go
const (
// 控制输出日志信息的细节,不能控制输出的顺序和格式。
// 输出的日志在每一项后会有一个冒号分隔:例如2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
Ldate = 1 << iota // 日期:2009/01/23
Ltime // 时间:01:23:23
Lmicroseconds // 微秒级别的时间:01:23:23.123123(用于增强Ltime位)
Llongfile // 文件全路径名+行号: /a/b/c/d.go:23
Lshortfile // 文件名+行号:d.go:23(会覆盖掉Llongfile)
LUTC // 使用UTC时间
LstdFlags = Ldate | Ltime // 标准logger的初始值
)
使用
go
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("这是一条很普通的日志。")

配置日志前缀
go
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("这是一条很普通的日志。")
log.SetPrefix("[pprof]")
log.Println("这是一条很普通的日志。")

配置日志输出位置
go
logFile, err := os.OpenFile("./xx.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("open log file failed, err:", err)
return
}
log.SetOutput(logFile)
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("这是一条很普通的日志。")
log.SetPrefix("[小王子]")
log.Println("这是一条很普通的日志。")

自定义日志
log标准库中还提供了一个创建新logger对象的构造函数--New,支持我们创建自己的logger示例。New函数的签名如下:
func New(out io.Writer, prefix string, flag int) *Logger
New创建一个Logger对象。其中,参数out设置日志信息写入的目的地。参数prefix会添加到生成的每一条日志前面。参数flag定义日志的属性(时间、文件等等)。
举个例子:
go
func main() {
logger := log.New(os.Stdout, "<New>", log.Lshortfile|log.Ldate|log.Ltime)
logger.Println("这是自定义的logger记录的日志。")
}
将上面的代码编译执行之后,得到结果如下:
go
<New>2025/08/06 17:43:45 main.go:15: 这是自定义的logger记录的日志。
总结 : Go内置的log库功能有限,例如无法满足记录不同级别日志的情况,我们在实际的项目中根据自己的需要选择使用第三方的日志库,如logrus、zap等。
Strconv
strconv包实现了基本数据类型与其字符串表示的转换,主要有以下常用函数:
Atoi()、
Itia()、
parse系列、
format系列、
append系列、
Atoi() string转int类型
go
func main() {
atoi, err := strconv.Atoi("ddd")
if err != nil {
if numErr, ok := err.(*strconv.NumError); ok {
fmt.Printf("解析错误: 输入值 '%s' 不是有效的整数\n", numErr.Num)
fmt.Printf("错误类型: %v\n", numErr.Err)
} else {
fmt.Printf("未知错误: %v\n", err)
}
} else {
fmt.Println("解析结果:", atoi)
}
}

go
func main() {
atoi, err := strconv.Atoi("1000")
if err != nil {
if numErr, ok := err.(*strconv.NumError); ok {
fmt.Printf("解析错误: 输入值 '%s' 不是有效的整数\n", numErr.Num)
fmt.Printf("错误类型: %v\n", numErr.Err)
} else {
fmt.Printf("未知错误: %v\n", err)
}
} else {
fmt.Println("解析结果:", atoi)
}
}

Itoa() 将int类型转(string)字符串
go
i2 := 200
s2 := strconv.Itoa(i2)
fmt.Printf("type:%T value:%#v\n", s2, s2)
//type:string value:"200"
字符串转其他类型
strconv.ParseInt 详细解析
go
func main() {
// ... 您现有的代码保持不变 ...
// 示例1: 十进制解析
num1, err := strconv.ParseInt("42", 10, 64)
if err != nil {
fmt.Println("解析错误:", err)
} else {
fmt.Println("十进制42解析结果:", num1)
}
// 示例2: 二进制解析
num2, err := strconv.ParseInt("1010", 2, 64)
if err != nil {
fmt.Println("解析错误:", err)
} else {
fmt.Println("二进制1010解析结果:", num2) // 输出10
}
// 示例3: 十六进制解析
num3, err := strconv.ParseInt("FF", 16, 64)
if err != nil {
fmt.Println("解析错误:", err)
} else {
fmt.Println("十六进制FF解析结果:", num3) // 输出255
}
// 示例4: 自动判断进制
num4, err := strconv.ParseInt("0xFF", 0, 64)
if err != nil {
fmt.Println("解析错误:", err)
} else {
fmt.Println("0xFF自动判断进制解析结果:", num4) // 输出255
}
// 示例5: 错误处理
_, err = strconv.ParseInt("12x3", 10, 64)
if err != nil {
if numErr, ok := err.(*strconv.NumError); ok {
fmt.Printf("解析错误: 输入值 '%s' 不是有效的整数\n", numErr.Num)
fmt.Printf("错误类型: %v\n", numErr.Err)
}
}
}


strconv.ParseBool
返回字符串表示的bool值。它接受1、0、t、f、T、F、true、false、True、False、TRUE、FALSE;否则返回错误。
go
func main() {
// 示例1: 真值(true)的各种表示形式
trueValues := []string{"1", "t", "T", "true", "TRUE", "True"}
for _, val := range trueValues {
b, err := strconv.ParseBool(val)
if err != nil {
fmt.Printf("'%s' 解析错误: %v\n", val, err)
} else {
fmt.Printf("'%s' → %t\n", val, b)
}
}
// 示例2: 假值(false)的各种表示形式
falseValues := []string{"0", "f", "F", "false", "FALSE", "False"}
for _, val := range falseValues {
b, err := strconv.ParseBool(val)
if err != nil {
fmt.Printf("'%s' 解析错误: %v\n", val, err)
} else {
fmt.Printf("'%s' → %t\n", val, b)
}
}
// 示例3: 无效输入
invalidValues := []string{"2", "yes", "no", "ture", "abc"}
for _, val := range invalidValues {
_, err := strconv.ParseBool(val)
if err != nil {
fmt.Printf("'%s' 是无效的布尔值: %v\n", val, err)
}
}
}
go
'1' → true
't' → true
'T' → true
'true' → true
'TRUE' → true
'True' → true
'0' → false
'f' → false
'F' → false
'false' → false
'FALSE' → false
'False' → false
'2' 是无效的布尔值: strconv.ParseBool: parsing "2": invalid syntax
'yes' 是无效的布尔值: strconv.ParseBool: parsing "yes": invalid syntax
'no' 是无效的布尔值: strconv.ParseBool: parsing "no": invalid syntax
'ture' 是无效的布尔值: strconv.ParseBool: parsing "ture": invalid syntax
'abc' 是无效的布尔值: strconv.ParseBool: parsing "abc": invalid syntax
ParseUnit()
ParseUint类似ParseInt但不接受正负号,用于无符号整型。
go
func main() {
// 示例1: 十进制无符号整数解析
num1, err := strconv.ParseUint("123", 10, 64)
if err != nil {
fmt.Println("解析错误:", err)
} else {
fmt.Println("十进制123解析结果:", num1)
}
// 示例2: 十六进制无符号整数解析
num2, err := strconv.ParseUint("FF", 16, 64)
if err != nil {
fmt.Println("解析错误:", err)
} else {
fmt.Println("十六进制FF解析结果:", num2) // 输出255
}
// 示例3: 二进制无符号整数解析
num3, err := strconv.ParseUint("1010", 2, 64)
if err != nil {
fmt.Println("解析错误:", err)
} else {
fmt.Println("二进制1010解析结果:", num3) // 输出10
}
// 示例4: 自动判断进制
num4, err := strconv.ParseUint("0xFF", 0, 64)
if err != nil {
fmt.Println("解析错误:", err)
} else {
fmt.Println("0xFF自动判断进制解析结果:", num4) // 输出255
}
// 示例5: 错误处理 - 负数会报错
_, err = strconv.ParseUint("-123", 10, 64)
if err != nil {
fmt.Println("负数解析错误:", err) // 输出: strconv.ParseUint: parsing "-123": invalid syntax
}
// 示例6: 超出范围错误
_, err = strconv.ParseUint("99999999999999999999", 10, 32)
if err != nil {
fmt.Println("超出范围错误:", err) // 输出: strconv.ParseUint: parsing "99999999999999999999": value out of range
}
}
go
十进制123解析结果: 123
十六进制FF解析结果: 255
二进制1010解析结果: 10
0xFF自动判断进制解析结果: 255
负数解析错误: strconv.ParseUint: parsing "-123": invalid syntax
超出范围错误: strconv.ParseUint: parsing "99999999999999999999": value out of range
ParseFloat()
如果s合乎语法规则,函数会返回最为接近s表示值的一个浮点数(使用IEEE754规范舍入)。
bitSize指定了期望的接收类型,32是float32(返回值可以不改变精确值的赋值给float32),64是float64;
返回值err是*NumErr类型的,语法有误的,err.Error=ErrSyntax;结果超出表示范围的,返回值f为±Inf,err.Error= ErrRange。
go
func main() {
// 示例1: 基本浮点数解析
f1, err := strconv.ParseFloat("3.1415926", 64)
if err != nil {
fmt.Println("解析错误:", err.Error())
} else {
fmt.Println("浮点数3.1415926解析结果:", f1)
}
// 示例2: 科学计数法解析
f2, err := strconv.ParseFloat("1.23e5", 64)
if err != nil {
fmt.Println("解析错误:", err.Error())
} else {
fmt.Println("科学计数法1.23e5解析结果:", f2) // 输出123000
}
// 示例3: 负浮点数解析
f3, err := strconv.ParseFloat("-123.456", 64)
if err != nil {
fmt.Println("解析错误:", err.Error())
} else {
fmt.Println("负浮点数-123.456解析结果:", f3)
}
// 示例4: 32位浮点数解析
f4, err := strconv.ParseFloat("0.123456789", 32)
if err != nil {
fmt.Println("解析错误:", err.Error())
} else {
fmt.Println("32位浮点数0.123456789解析结果:", f4) // 注意精度损失
}
// 示例5: 错误处理 - 无效格式
_, err = strconv.ParseFloat("12x.34", 64)
if err != nil {
fmt.Println("无效格式错误:", err.Error()) // 输出: strconv.ParseFloat: parsing "12x.34": invalid syntax
}
// 示例6: 错误处理 - 超出范围
_, err = strconv.ParseFloat("1e309", 64)
if err != nil {
fmt.Println("超出范围错误:", err) // 输出: strconv.ParseFloat: parsing "1e309": value out of range
}
}
Format 其他类型转字符串
FormatBool()
go
func FormatBool(b bool) string
go
func main() {
// ... 您现有的其他代码保持不变 ...
// 示例1: 基本转换
b1 := true
s1 := strconv.FormatBool(b1)
fmt.Println("true 转换为:", s1) // 输出: true
// 示例2: false转换
b2 := false
s2 := strconv.FormatBool(b2)
fmt.Println("false 转换为:", s2) // 输出: false
// 示例3: 条件表达式结果转换
age := 20
isAdult := age >= 18
s3 := strconv.FormatBool(isAdult)
fmt.Printf("年龄%d岁是否成年: %s\n", age, s3) // 输出: 年龄20岁是否成年: true
// 示例4: 与ParseBool配合使用
input := "TRUE"
b, _ := strconv.ParseBool(input)
output := strconv.FormatBool(b)
fmt.Printf("输入:%s → 解析后:%t → 重新格式化:%s\n", input, b, output)
// 输出: 输入:TRUE → 解析后:true → 重新格式化:true
}

FormatInt()
go
func main() {
// 示例1: 十进制转换
num1 := int64(42)
println(num1)
s1 := strconv.FormatInt(num1, 10)
fmt.Println("十进制42转换为:", s1) // 输出: 42
// 示例2: 二进制转换
num2 := int64(10)
s2 := strconv.FormatInt(num2, 2)
fmt.Println("十进制10转换为二进制:", s2) // 输出: 1010
// 示例3: 十六进制转换
num3 := int64(255)
s3 := strconv.FormatInt(num3, 16)
fmt.Println("十进制255转换为十六进制:", s3) // 输出: ff
// 示例4: 八进制转换
num4 := int64(8)
s4 := strconv.FormatInt(num4, 8)
fmt.Println("十进制8转换为八进制:", s4) // 输出: 10
// 示例5: 负数转换
num5 := int64(-42)
s5 := strconv.FormatInt(num5, 10)
fmt.Println("负数-42转换为:", s5) // 输出: -42
// 示例6: 大数转换
num6 := int64(1<<63 - 1) // 最大int64值
s6 := strconv.FormatInt(num6, 10)
fmt.Println("最大int64值转换为:", s6) // 输出: 9223372036854775807
}
go
42
十进制42转换为: 42
十进制10转换为二进制: 1010
十进制255转换为十六进制: ff
十进制8转换为八进制: 10
负数-42转换为: -42
最大int64值转换为: 9223372036854775807
FormatUint()
go
func main() {
// 示例1: 十进制转换
num1 := uint64(42)
s1 := strconv.FormatUint(num1, 10)
fmt.Println("十进制42转换为:", s1) // 输出: 42
// 示例2: 二进制转换
num2 := uint64(10)
s2 := strconv.FormatUint(num2, 2)
fmt.Println("十进制10转换为二进制:", s2) // 输出: 1010
// 示例3: 十六进制转换
num3 := uint64(255)
s3 := strconv.FormatUint(num3, 16)
fmt.Println("十进制255转换为十六进制:", s3) // 输出: ff
// 示例4: 八进制转换
num4 := uint64(8)
s4 := strconv.FormatUint(num4, 8)
fmt.Println("十进制8转换为八进制:", s4) // 输出: 10
// 示例5: 大数转换
num5 := uint64(1<<64 - 1) // 最大uint64值
s5 := strconv.FormatUint(num5, 10)
fmt.Println("最大uint64值转换为:", s5) // 输出: 18446744073709551615
// 示例6: 自定义进制转换
num6 := uint64(35)
s6 := strconv.FormatUint(num6, 36) // 36进制
fmt.Println("十进制35转换为36进制:", s6) // 输出: z (36进制中z表示35)
}
go
十进制42转换为: 42
十进制10转换为二进制: 1010
十进制255转换为十六进制: ff
十进制8转换为八进制: 10
最大uint64值转换为: 18446744073709551615
十进制35转换为36进制: z
FormatFloat()

go
func main() {
// 示例1: 普通小数格式
f1 := 123.456789
s1 := strconv.FormatFloat(f1, 'f', 2, 64)
fmt.Println("保留2位小数:", s1) // 输出: 123.46
// 示例2: 科学计数法
f2 := 123456.789
s2 := strconv.FormatFloat(f2, 'e', 3, 64)
fmt.Println("科学计数法:", s2) // 输出: 1.235e+05
// 示例3: 自动选择格式
f3 := 123456.789
s3 := strconv.FormatFloat(f3, 'g', 6, 64)
fmt.Println("自动格式:", s3) // 输出: 123456.789
// 示例4: 32位浮点数
f4 := float32(123.456789)
s4 := strconv.FormatFloat(float64(f4), 'f', 4, 32)
fmt.Println("32位浮点数:", s4) // 输出: 123.4568
// 示例5: 大数处理
f5 := 1.23456789e20
s5 := strconv.FormatFloat(f5, 'G', 8, 64)
fmt.Println("大数处理:", s5) // 输出: 1.2345679e+20
}
go
保留2位小数: 123.46
科学计数法: 1.235e+05
自动格式: 123457
32位浮点数: 123.4568
大数处理: 1.2345679E+20
其他
isPrint()
返回一个字符是否是可打印的,和unicode.IsPrint一样,r必须是:字母(广义)、数字、标点、符号、ASCII空格。
go
func main() {
// 示例1: 可打印字符
fmt.Println("字母A:", strconv.IsPrint('A')) // true
fmt.Println("数字1:", strconv.IsPrint('1')) // true
fmt.Println("空格:", strconv.IsPrint(' ')) // true
fmt.Println("中文:", strconv.IsPrint('中')) // true
fmt.Println("标点:", strconv.IsPrint('!')) // true
fmt.Println("换行符:", strconv.IsPrint('\n')) // true
// 示例2: 不可打印字符
fmt.Println("控制字符:", strconv.IsPrint('\x00')) // false
fmt.Println("退格:", strconv.IsPrint('\b')) // false
fmt.Println("铃响:", strconv.IsPrint('\a')) // false
fmt.Println("删除:", strconv.IsPrint('\x7f')) // false
// 示例3: 字符串中字符检查
str := "Hello\t世界!\n"
for i, r := range str {
if !strconv.IsPrint(r) {
fmt.Printf("位置 %d 的字符 %U 不可打印\n", i, r)
}
}
}
go
字母A: true
数字1: true
空格: true
中文: true
标点: true
换行符: false
控制字符: false
退格: false
铃响: false
删除: false
位置 5 的字符 U+0009 不可打印
位置 13 的字符 U+000A 不可打印
Http
Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现。
get请求
go
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
// 示例1: 基本GET请求
resp, err := http.Get("https://www.baidu.com")
if err != nil {
fmt.Println("请求错误:", err)
return
}
defer resp.Body.Close()
// 打印响应状态
fmt.Println("状态码:", resp.Status)
fmt.Println("响应头:", resp.Header)
for key, values := range resp.Header {
fmt.Println(key, ":", values)
}
// 示例2: 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("读取响应体错误:", err)
return
}
fmt.Println("响应体长度:", len(body))
fmt.Println("响应体内容:", string(body))
// 示例3: 将响应保存到文件
file, err := os.Create("baidu.html")
if err != nil {
fmt.Println("创建文件错误:", err)
return
}
defer file.Close()
_, err = file.Write(body)
if err != nil {
fmt.Println("写入文件错误:", err)
return
}
fmt.Println("网页已保存到 baidu.html")
}

带参数的GET请求示例
go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
func main() {
apiUrl := "http://127.0.0.1:9090/get"
// URL param
data := url.Values{}
data.Set("name", "枯藤")
data.Set("age", "18")
u, err := url.ParseRequestURI(apiUrl)
fmt.Println("uuuu==111==>", u.String())
if err != nil {
fmt.Printf("parse url requestUrl failed,err:%v\n", err)
}
u.RawQuery = data.Encode() // URL encode
fmt.Println("uuuu==222==>", u.String())
resp, err := http.Get(u.String())
if err != nil {
fmt.Println("post failed, err:%v\n", err.Error())
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("get resp failed,err:%v\n", err)
return
}
fmt.Println(string(b))
}

Post请求示例
上面演示了使用net/http包发送GET请求的示例,发送POST请求的示例代码如下:
go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
)
// net/http post demo
func main() {
url := "http://tp.demos.xp/post"
// 表单数据
//contentType := "application/x-www-form-urlencoded"
//data := "name=枯藤&age=18"
// json
contentType := "application/json"
data := `{"name":"nicolas","age":18}`
resp, err := http.Post(url, contentType, strings.NewReader(data))
if err != nil {
fmt.Println("post failed, err:%v\n", err)
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("get resp failed,err:%v\n", err)
return
}
fmt.Println(string(b))
}
}
数据格式
json
go
package main
import (
"encoding/json"
"fmt"
)
// net/http post demo
type Person struct {
Name string
Hobby string
}
func main() {
p := Person{"baidu.com", "女"}
// 编码json
b, err := json.Marshal(p)
if err != nil {
fmt.Println("json err ", err)
}
fmt.Println(string(b))
// 格式化输出
b, err = json.MarshalIndent(p, "", " ")
if err != nil {
fmt.Println("json err ", err)
}
fmt.Println(string(b))
}
go
{"Name":"5lmh.com","Hobby":"女"}
{
"Name": "5lmh.com",
"Hobby": "女"
}
xml
go
package main
import (
"encoding/xml"
"fmt"
"io/ioutil"
)
// 抽取单个server对象
type Server struct {
ServerName string `xml:"serverName"`
ServerIP string `xml:"serverIP"`
}
type Servers struct {
Name xml.Name `xml:"servers"`
Version int `xml:"version"`
Servers []Server `xml:"server"`
}
func main() {
data, err := ioutil.ReadFile("my.xml")
if err != nil {
fmt.Println(err)
return
}
var servers Servers
err = xml.Unmarshal(data, &servers)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("xml: %#v\n", servers)
}
go
xml: main.Servers{Name:xml.Name{Space:"", Local:""}, Version:1, Servers:[]main.Server{main.Server{ServerName:"Server1", ServerIP:"192.168.1.1"}, main.Server{ServerName:"Server2", ServerIP:"192.168.1.2"}}}