向外輸出
fmt包實現了類似C語言printf和scanf的格式化I/O。主要分為向外輸出內容和獲取輸入內容兩大部分。
內置輸出
不需要引入標準庫,方便
package mainfunc main() {print("我是控制臺打印,我不換行 可以自己控制換行 \n我是另一行")println("Hello World")}
fmt標準輸出
Print系列函數會將內容輸出到系統的標準輸出,
區別在于Print函數直接輸出內容,
Printf函數支持格式化輸出字符串,
Println函數會在輸出內容的結尾添加一個換行符。
package mainimport "fmt"type User struct {Name stringAge 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中,我們通常用這個函數往文件中寫入內容。
// 默認輸出到控制臺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.Bufferfmt.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系列函數會把傳入的數據生成并返回一個字符串。
該放大的接口定義
func Sprint(a ...interface{}) string
func Sprintf(format string, a ...interface{}) string
func Sprintln(a ...interface{}) string
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參數生成格式化字符串并返回一個包含該字符串的錯誤。
func Errorf(format string, a ...interface{}) error
通常使用這種方式來自定義錯誤類型,例如:
err := fmt.Errorf("這是一個錯誤")fmt.Println(err)
打印:
這是一個錯誤
格式化占位符
fmt.Printf("%v\n", 100)fmt.Printf("%v\n", false)o := struct {name stringage 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")
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)
func main() {s := "枯藤"fmt.Printf("%s\n", s)fmt.Printf("%q\n", s)fmt.Printf("%x\n", s)fmt.Printf("%X\n", s)
}
a := 18
fmt.Printf("%p\n", &a)
fmt.Printf("%#p\n", &a)
n := 88.99fmt.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
三個函數,可以在程序運行過程中從標準輸入獲取用戶的輸入。
func main() {var (name stringage intmarried bool)fmt.Scan(&name, &age, &married)fmt.Printf("掃描結果 name:%s age:%d married:%t \n", name, age, married)
}
Time 時間
時間和日期是我們編程中經常會用到的,本文主要介紹了Go語言內置的time包的基本用法。
時間類型
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億納秒)
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方法如下:
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 求兩個時間之間的差值
now := time.Now()fmt.Println("開始時間:", now)// 正確用法:需要一個另一個時間對象來調用Sublater := 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)
開始時間: 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 兩個時間是否相等
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之前,返回真;否則返回假。
func (t Time) Before(u Time) bool
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)) // truefmt.Println("now在past之前?", now.Before(past)) // falsefmt.Println("future在now之前?", future.Before(now)) // false
}
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之后,返回真;否則返回假。
func (t Time) After(u Time) bool
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
now在future之后? false
now在past之后? true
future在now之后? true
實際場景的應用
- 檢查任務是否超時
deadline := time.Now().Add(2 * time.Second)time.Sleep(3 * time.Second)// ... 執行一些耗時操作 ...if time.Now().After(deadline) {fmt.Println("任務已超時")return}fmt.Println("任務已完成")
任務已超時
- 驗證證書有效期
expiryDate := time.Date(2023, 12, 31, 0, 0, 0, 0, time.UTC)
if time.Now().After(expiryDate) {fmt.Println("證書已過期")
} else {fmt.Println("證書仍在有效期內")
}
證書已過期
- 定時器檢查
在這里插入代碼片
func main() {lastCheck := time.Now()nextCheck := lastCheck.Add(3 * time.Second)time.Sleep(4 * time.Second)if time.Now().After(nextCheck) {fmt.Println("需要執行定期檢查了")// 執行檢查邏輯...}
}
需要執行定期檢查了
- 與Before配合使用
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("當前在時間范圍內")}
當前在時間范圍內
定時器
使用time.Tick(時間間隔)來設置定時器,定時器的本質上是一個通道(channel)。
ticker := time.Tick(time.Second) //定義一個1秒間隔的定時器for i := range ticker {fmt.Println(i) //每秒都會執行的任務}
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)
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"))
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
解析字符串格式的時間
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))
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包基本使用
導入包
import flag
flag參數類型
實例1
var name stringvar age intvar married boolvar delay time.Durationflag.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)
PS E:\work\code\go\demo> go run main.go -name 李四 -age 25 -married=true -d 1h30m
姓名: 李四
年齡: 25
婚否: true
時間間隔: 1h30m0sPS E:\work\code\go\demo> go run main.go
姓名: 張三
年齡: 18
婚否: false
時間間隔: 0s
實例2
package mainimport ("flag""fmt""time"
)type User struct {Name stringAge int
}func main() {//定義命令行參數方式1var name stringvar age intvar married boolvar delay time.Durationflag.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 run main.go --help
命令2,使用默認參數
go run main.go
命令2,填寫所需要的參數
錯誤寫法
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 run main.go -age 800 -d 22m -married -name 李白
李白未婚
則 直接取掉-married
go run main.go -age 800 -d 22m -name 李白
OS
更詳細的OS 請看鏈接
添加鏈接描述
- Getwd 獲取當前工作目錄
package mainimport ("os"
)func main() {dir, err := os.Getwd()if err != nil {panic(err)}println(dir)}
E:\work\code\go\demo
- 創建文件
package mainimport "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
log.Println("這是一條很普通的日志。")v := "很普通的"log.Printf("這是一條%s日志。\n", v)log.Fatalln("這是一條會觸發fatal的日志。")log.Panicln("這是一條會觸發panic的日志。")
配置logger
1 flag選項
const (// 控制輸出日志信息的細節,不能控制輸出的順序和格式。// 輸出的日志在每一項后會有一個冒號分隔:例如2009/01/23 01:23:23.123123 /a/b/c/d.go:23: messageLdate = 1 << iota // 日期:2009/01/23Ltime // 時間:01:23:23Lmicroseconds // 微秒級別的時間:01:23:23.123123(用于增強Ltime位)Llongfile // 文件全路徑名+行號: /a/b/c/d.go:23Lshortfile // 文件名+行號:d.go:23(會覆蓋掉Llongfile)LUTC // 使用UTC時間LstdFlags = Ldate | Ltime // 標準logger的初始值
)
使用
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.Println("這是一條很普通的日志。")
配置日志前綴
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)log.Println("這是一條很普通的日志。")log.SetPrefix("[pprof]")log.Println("這是一條很普通的日志。")
配置日志輸出位置
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定義日志的屬性(時間、文件等等)。
舉個例子:
func main() {logger := log.New(os.Stdout, "<New>", log.Lshortfile|log.Ldate|log.Ltime)logger.Println("這是自定義的logger記錄的日志。")
}
將上面的代碼編譯執行之后,得到結果如下:
<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類型
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)}
}
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)字符串
i2 := 200
s2 := strconv.Itoa(i2)
fmt.Printf("type:%T value:%#v\n", s2, s2)
//type:string value:"200"
字符串轉其他類型
strconv.ParseInt 詳細解析
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;否則返回錯誤。
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)}}
}
'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但不接受正負號,用于無符號整型。
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}
}
十進制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。
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()
func FormatBool(b bool) string
func main() {// ... 您現有的其他代碼保持不變 ...// 示例1: 基本轉換b1 := trues1 := strconv.FormatBool(b1)fmt.Println("true 轉換為:", s1) // 輸出: true// 示例2: false轉換b2 := falses2 := strconv.FormatBool(b2)fmt.Println("false 轉換為:", s2) // 輸出: false// 示例3: 條件表達式結果轉換age := 20isAdult := age >= 18s3 := 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()
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
}
42
十進制42轉換為: 42
十進制10轉換為二進制: 1010
十進制255轉換為十六進制: ff
十進制8轉換為八進制: 10
負數-42轉換為: -42
最大int64值轉換為: 9223372036854775807
FormatUint()
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)
}
十進制42轉換為: 42
十進制10轉換為二進制: 1010
十進制255轉換為十六進制: ff
十進制8轉換為八進制: 10
最大uint64值轉換為: 18446744073709551615
十進制35轉換為36進制: z
FormatFloat()
func main() {// 示例1: 普通小數格式f1 := 123.456789s1 := strconv.FormatFloat(f1, 'f', 2, 64)fmt.Println("保留2位小數:", s1) // 輸出: 123.46// 示例2: 科學計數法f2 := 123456.789s2 := strconv.FormatFloat(f2, 'e', 3, 64)fmt.Println("科學計數法:", s2) // 輸出: 1.235e+05// 示例3: 自動選擇格式f3 := 123456.789s3 := 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.23456789e20s5 := strconv.FormatFloat(f5, 'G', 8, 64)fmt.Println("大數處理:", s5) // 輸出: 1.2345679e+20}
保留2位小數: 123.46
科學計數法: 1.235e+05
自動格式: 123457
32位浮點數: 123.4568
大數處理: 1.2345679E+20
其他
isPrint()
返回一個字符是否是可打印的,和unicode.IsPrint一樣,r必須是:字母(廣義)、數字、標點、符號、ASCII空格。
func main() {// 示例1: 可打印字符fmt.Println("字母A:", strconv.IsPrint('A')) // truefmt.Println("數字1:", strconv.IsPrint('1')) // truefmt.Println("空格:", strconv.IsPrint(' ')) // truefmt.Println("中文:", strconv.IsPrint('中')) // truefmt.Println("標點:", strconv.IsPrint('!')) // truefmt.Println("換行符:", strconv.IsPrint('\n')) // true// 示例2: 不可打印字符fmt.Println("控制字符:", strconv.IsPrint('\x00')) // falsefmt.Println("退格:", strconv.IsPrint('\b')) // falsefmt.Println("鈴響:", strconv.IsPrint('\a')) // falsefmt.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)}}
}
字母A: true
數字1: true
空格: true
中文: true
標點: true
換行符: false
控制字符: false
退格: false
鈴響: false
刪除: false
位置 5 的字符 U+0009 不可打印
位置 13 的字符 U+000A 不可打印
Http
Go語言內置的net/http包十分的優秀,提供了HTTP客戶端和服務端的實現。
get請求
package mainimport ("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請求示例
package mainimport ("fmt""io/ioutil""net/http""net/url"
)func main() {apiUrl := "http://127.0.0.1:9090/get"// URL paramdata := 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 encodefmt.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請求的示例代碼如下:
package mainimport ("fmt""io/ioutil""net/http""strings"
)// net/http post demofunc main() {url := "http://tp.demos.xp/post"// 表單數據//contentType := "application/x-www-form-urlencoded"//data := "name=枯藤&age=18"// jsoncontentType := "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
package mainimport ("encoding/json""fmt"
)// net/http post demo
type Person struct {Name stringHobby string
}func main() {p := Person{"baidu.com", "女"}// 編碼jsonb, 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))
}
{"Name":"5lmh.com","Hobby":"女"}
{"Name": "5lmh.com","Hobby": "女"
}
xml
package mainimport ("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 Serverserr = xml.Unmarshal(data, &servers)if err != nil {fmt.Println(err)return}fmt.Printf("xml: %#v\n", servers)
}
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"}}}