02 Go標準庫
阿新 • • 發佈:2022-05-18
package main
// time模組
// 時間型別
//func main() {
//now := time.Now() // 獲取當前時間
//fmt.Println(now)
//
//year := now.Year()
//month := now.Month()
//day := now.Day()
//hour := now.Hour()
//minute := now.Minute()
//second := now.Second()
//fmt.Printf("%d-%02d-%02d-%02d:%02d:%02d", year, month, day, hour, minute, second)
//}
// 時間戳
//func main() {
//now := time.Now()
//timestamp1 := now.Unix() //秒級時間戳
//timestamp2 := now.UnixNano() //納秒級時間戳
//fmt.Printf("current timestamp1:%v\n", timestamp1)
//fmt.Printf("current timestamp2:%v\n", timestamp2)
//// 將時間戳轉為時間格式
//timestamp3 := now.Unix()
//timeObj := time.Unix(timestamp3, 0)
//year := timeObj.Year()
//fmt.Println(year)
//}
// 時間間隔、納秒、微妙、毫秒、秒、分、時
//func main() {
////const (
////Nanosecond Duration = 1
////Microsecond = 1000 * Nanosecond
////Millisecond = 1000 * Microsecond
////Second = 1000 * Millisecond
////Minute = 60 * Second
////Hour = 60 * Minute
////)
//time.Sleep(time.Millisecond * 20) //暫停20s
//}
// 時間格式化
//func main() {
//// 按格式模板進行時間格式化
//now := time.Now()
//s1 := now.Format("2006-01-02 15:04:05 Mon Jan")
//fmt.Println(s1)
//// 字串轉時間型別
//loc, _ := time.LoadLocation("Asia/Shanghai")
//timeObj, err := time.ParseInLocation("2006-01-02 15:04:05", "2022-03-27 20:49:20", loc)
//if err != nil {
// fmt.Println(err)
// return
//}
//fmt.Println(timeObj)
//}
// 時間操作函式
//func main() {
//// Add 方法,1分鐘前
//now := time.Now()
//fmt.Println("now:", now)
//m, _ := time.ParseDuration("-1m")
//m1 := now.Add(m)
//fmt.Println("now add - 1m:", m1)
//// Add 方法,1分鐘之後
//mm, _ := time.ParseDuration("1m")
//mm1 := now.Add(mm)
//fmt.Println("now add + 1m", mm1)
//// Sub方法,兩個時間差
//fmt.Println(now.Sub(m1))
//}
2 fmt
package main
////佔位符
//func main() {
//fmt.Println("張三", "李四", "王二")
//name := "張三"
//age := 20
//fmt.Printf("%s 今年 %d 歲\n", name, age)
//fmt.Printf("值: %v ---> 型別: %T", name, name)
//}
// Sprint -> 把傳入的資料生成並返回一個字串
//func main() {
//s1 := fmt.Sprintf("枯藤")
//fmt.Println(s1)
//name := "枯藤"
//age := 20
//s2 := fmt.Sprintf("name:%s age:%d", name, age)
//fmt.Println(s2)
//s3 := fmt.Sprintln("枯藤")
//fmt.Println(s3)
//s4 := fmt.Sprint("hh")
//fmt.Println(s4)
//s5 := fmt.Sprintf("1")
//fmt.Println(s5)
//}
3 net/http
index.html
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:9090/post" enctype="application/x-www-form-urlencoded" method="post">
<label>
姓名: <input type="text" name="name">
</label>
<label>
<br/>
年齡: <input type="text" name="age">
</label>
<br/>
提交:<input type="submit">
</form>
</body>
</html>
main.go
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
)
// net/http包實現http客戶端和服務端
// get請求網站示例
func getBaidu(url string) {
resp, err := http.Get(url)
if err != nil {
fmt.Printf("get failed,err:%v\n", err)
return
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
fmt.Printf("resp status failed, err:%v\n", err)
return
}
}(resp.Body)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("read from resp.Body failed, err:%v", err)
return
}
fmt.Println(string(body))
}
func testServer(w http.ResponseWriter, r *http.Request) {
_, err := w.Write([]byte("這是http server端"))
if err != nil {
fmt.Println("test server failed!")
return
}
}
// 帶引數的get
func getHandler(w http.ResponseWriter, r *http.Request) {
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
fmt.Println("request close failed!", err)
return
}
}(r.Body)
data := r.URL.Query()
fmt.Println(data.Get("name"))
fmt.Println(data.Get("age"))
_, err := w.Write([]byte(`{"status":ok}`))
if err != nil {
fmt.Println("response failed!", err)
return
}
}
// post請求
func postHandler(w http.ResponseWriter, r *http.Request) {
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
fmt.Println(err)
return
}
}(r.Body)
// 1. 請求型別是application/x-www-form-urlencoded時解析form資料
err := r.ParseForm()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("列印form資料", r.PostForm)
fmt.Println("列印form資料", r.PostForm.Get("name"), r.PostForm.Get("age"))
// 2. 請求型別是application/json時從r.Body讀取資料
//b, err := ioutil.ReadAll(r.Body)
//if err != nil {
//fmt.Println(err)
//return
//}
//fmt.Println(string(b))
_, err = w.Write([]byte(`"status": "ok"`))
if err != nil {
fmt.Println(err)
return
}
}
func main() {
// get請求網站示例
//getBaidu("https://taobao.com")
// 路由服務
// http://127.0.0.1:9090/
http.HandleFunc("/", testServer)
// http://127.0.0.1:9090/get?name="小王子"&age=18
http.HandleFunc("/get", getHandler)
/*輸出結果
"小王子"
19
*/
// 訪問index.html
http.HandleFunc("/post", postHandler)
/* 輸出結果
列印form資料 map[age:[18] name:[劉暢]]
列印form資料 劉暢 18
*/
// 啟動服務
fmt.Println("http server http://127.0.0.1:9090 start")
err := http.ListenAndServe(":9090", nil)
if err != nil {
fmt.Printf("http server failed, err:%v\n", err)
return
}
}
4 strconv
package main
import (
"fmt"
"strconv"
)
// strconv包實現了基本資料型別與其字串表示的轉換,主要有以下常用函式: Atoi()、Itoa()、parse系列、format系列、append系列。
// base指定進位制(2到36),如果base為0,則會從字串前置判斷,”0x”是16進位制,”0”是8進位制,否則是10進位制;
// bitSize指定結果必須能無溢位賦值的整數型別,0、8、16、32、64 分別代表 int、int8、int16、int32、int64;
// Atoi() 函式用於將字串型別的整數轉換為int型別
func strToInt() {
s1 := "100"
i1, err := strconv.Atoi(s1)
if err != nil {
fmt.Println("can't convert to int", err)
return
}
fmt.Printf("Type:%T value:%#v", i1, i1)
}
//Itoa()函式將int型別資料轉換為對應的字串表示
func intToStr() {
i2 := 200
s2 := strconv.Itoa(i2)
fmt.Printf("Type:%T value:%#v", s2, s2)
}
//Parse類函式用於轉換字串為給定型別的值:ParseBool()、ParseFloat()、ParseInt()、ParseUint()。
func parseStrTo() {
//1、字串轉Bool
b, err := strconv.ParseBool("true")
if err != nil {
fmt.Println("can't convert to bool", err)
return
}
fmt.Printf("type:%T value:%#v\n", b, b)
//2、字串轉Float
f, err := strconv.ParseFloat("3.1415", 64)
if err != nil {
fmt.Println("can't convert str to float", err)
return
}
fmt.Printf("Type:%T value:%#v\n", f, f)
//3、字串轉Int(接受正負號)
i, err := strconv.ParseInt("-100", 10, 64)
if err != nil {
fmt.Println("can't str to int", err)
}
fmt.Printf("Type:%T value:%#v\n", i, i)
//4、字串轉Uint(不接受正負號)
u, err := strconv.ParseUint("200", 10, 64)
if err != nil {
fmt.Println("can't str to Unit", err)
}
fmt.Printf("Type:%T value:%v\n", u, u)
}
// Format系列函式實現了將給定型別資料格式化為string型別資料的功能。
func formatToStr() {
//1、Bool轉字串
b := strconv.FormatBool(true)
fmt.Printf("type:%T value:%#v\n", b, b)
//2、Float轉字串
f := strconv.FormatFloat(3.1415, 'f', -1, 64)
fmt.Printf("Type:%T value:%#v\n", f, f)
//3、Int轉字串(接受正負號)
i := strconv.FormatInt(-100, 10)
fmt.Printf("Type:%T value:%#v\n", i, i)
//4、Uint(不接受正負號)轉字串
u := strconv.FormatUint(200, 10)
fmt.Printf("Type:%T value:%v\n", u, u)
}
func main() {
//strToInt()
//intToStr()
//parseStrTo()
//formatToStr()
}
5 OS
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
)
//os標準庫
//func main() {
//1、獲取當前目錄
//fmt.Println(os.Getwd())
//2、修改當前目錄
//err := os.Chdir("d:\\code\\GoCode")
//if err != nil {
//return
//}
//fmt.Println(os.Getwd())
//3、建立資料夾
//err := os.Mkdir("lc_dir", 777)
//if err != nil {
//return
//}
//4、刪除檔案或者資料夾
//err := os.Remove("lc_dir")
//if err != nil {
//return
//}
//5、修改資料夾或檔案的名稱
//err := os.Rename("lc.txt", "chang.txt")
//if err != nil {
//return
//}
//6、新建檔案
//_, err := os.Create("lc.txt")
//if err != nil {
//return
//}
//7、開啟檔案並寫入檔案
/*
O_RDONLY 開啟只讀檔案
O_WRONLY 開啟只寫檔案
O_RDWR 開啟既可以讀取又可以寫入檔案
O_APPEND 寫入檔案時將資料追加到檔案尾部
O_CREATE 如果檔案不存在,則建立一個新的檔案
*/
//file, err1 := os.OpenFile("file.txt", os.O_RDWR|os.O_APPEND|os.O_CREATE, 644)
//if err1 != nil {
//return
//}
//_, err2 := file.WriteString(",你好222")
//if err2 != nil {
//return
//}
//err3 := file.Close()
//if err3 != nil {
//return
//}
//}
//// 從檔案中讀取指定位元組數
//func main() {
//fileObj, err := os.Open("./15OS/os.txt")
//if err != nil {
// fmt.Printf("open file error,err:%v\n", err)
// return
//}
////關閉檔案
//defer func(fileObj *os.File) {
// err := fileObj.Close()
// if err != nil {
// return
// }
//}(fileObj)
////讀取檔案內容
//var tmp = make([]byte, 128)
//n, err := fileObj.Read(tmp)
//if err != nil {
// fmt.Printf("read from file failed,err:%v\n", err)
// return
//}
//fmt.Printf("read %d bytes from file.\n", n)
//fmt.Println(string(tmp[:n]))
//}
// 迴圈讀取檔案中所有的位元組數,需要每次指定讀取的位元組數
//func main() {
//fileObj, err := os.Open("./15OS/os.txt")
//if err != nil {
// fmt.Printf("open file error,err:%v\n", err)
// return
//}
////關閉檔案
//defer func(fileObj *os.File) {
// err := fileObj.Close()
// if err != nil {
// return
// }
//}(fileObj)
////讀取檔案內容
//var content []byte
//var tmp = make([]byte, 128)
//for {
// n, err := fileObj.Read(tmp)
// if err == io.EOF { // EOF => End Of File
// fmt.Println("檔案讀完了")
// break
// }
// if err != nil {
// fmt.Printf("read from file failed,err:%v\n", err)
// return
// }
// fmt.Printf("read %d bytes from file.\n", n)
// content = append(content, tmp[:n]...)
//}
////fmt.Printf("%#v", string(content))
//fmt.Println(string(content))
//}
// read by bufio從檔案中讀取檔案,一行一行的讀取
//func main() {
//fileObj, err := os.Open("./15OS/os.txt")
//if err != nil {
// fmt.Printf("open file error,err:%v\n", err)
// return
//}
////關閉檔案
//defer func(fileObj *os.File) {
// err := fileObj.Close()
// if err != nil {
// return
// }
//}(fileObj)
////讀取檔案內容
//reader := bufio.NewReader(fileObj)
//for {
// line, err := reader.ReadString('\n')
// if err == io.EOF {
// if len(line) != 0 {
// fmt.Println(line)
// }
// fmt.Println("檔案讀完了")
// return
// }
// if err != nil {
// fmt.Println("read file failed,err:", err)
// return
// }
// //fmt.Printf("%#v", line)
// fmt.Print(line)
//}
//}
// ioutil讀取整個檔案內容
//func main() {
//content, err := ioutil.ReadFile("./15OS/os.txt")
//if err != nil {
// fmt.Println("read file failed, err:", err)
// return
//}
//fmt.Println(string(content))
//}
// 檔案寫入操作Write、WriteString
func writeString(str string, fileName string) {
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("open file failed, err:", err)
return
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
fmt.Println("open file close failed, err:", err)
return
}
}(file)
_, err = file.Write([]byte(str)) //寫入位元組切片資料
if err != nil {
fmt.Println("write file failed, err:", err)
return
}
_, err = file.WriteString(str) // 直接寫入字串資料
if err != nil {
fmt.Println("writeString file failed, err:", err)
return
}
}
// bufio.NewWriter,寫快取
func bufIoCache(str string, fileName string) {
file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 644)
if err != nil {
fmt.Println("open file failed, err:", err)
return
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
fmt.Println("open file close failed, err:", err)
return
}
}(file)
// 先將資料寫到快取
write := bufio.NewWriter(file)
_, err = write.WriteString(str)
if err != nil {
fmt.Println("writeString file failed, err:", err)
return
}
//將快取中的內容寫入檔案
err = write.Flush()
if err != nil {
fmt.Println("writeString file flush failed, err:", err)
return
}
}
// ioutil.WriteFile,一次性寫入,覆蓋之前的內容
func ioUtilWriteFile(str, fileName string) {
err := ioutil.WriteFile(fileName, []byte(str), 0664)
if err != nil {
fmt.Println("write file failed, error:", err)
return
}
}
// io.Copy() 實現檔案copy操作,可以複製文字或二進位制檔案
func copyFile(dstName, srcName string) (written int64, err error) {
//以讀的方式開啟原始檔
src, err := os.Open(srcName)
if err != nil {
fmt.Printf("open %s failed ,err:%v.\n", srcName, err)
return
}
defer func(src *os.File) {
err := src.Close()
if err != nil {
fmt.Printf("src %s close failed, err:%v", srcName, err)
return
}
}(src)
// 以寫|建立的方式開啟目標檔案
dst, err := os.OpenFile(dstName, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Printf("open %s failed, err:%v. \n", dstName, err)
}
defer func(dst *os.File) {
err := dst.Close()
if err != nil {
fmt.Printf("close %s failed, err:%v.\n", dstName, err)
return
}
}(dst)
//呼叫io.Copy()拷貝內容
return io.Copy(dst, src)
}
func main() {
// 檔案寫入操作Write、WriteString
//writeString("你好,中國\n", "15OS/out.txt")
// bufio.NewWriter,寫快取
//bufIoCache("愛拼才會贏\n", "15OS/out.txt")
// ioutil.WriteFile,一次性寫入,覆蓋之前的內容
//ioUtilWriteFile("努力學習go語言", "15OS/out.txt")
// io.Copy() 實現檔案copy操作,可以複製文字或二進位制檔案
//_, err := copyFile("15OS/sogou_pinyin1.exe", "15OS/sogou_pinyin.exe")
//if err != nil {
//fmt.Println("copy file failed,err", err)
//return
//}
//fmt.Println("copy done!")
}
6 flag
package main
import (
"flag"
"fmt"
"os"
"time"
)
// Go語言內建的flag包實現了命令列引數的解析,flag包使得開發命令列工具更為簡單。
// os.Args
//如果你只是簡單的想要獲取命令列引數,可以像下面的程式碼示例一樣使用os.Args來獲取命令列引數。
//os.Args是一個儲存命令列引數的字串切片,它的第一個元素是執行檔案的名稱。
func argsLen() {
if len(os.Args) > 0 {
for index, arg := range os.Args {
fmt.Printf("args[%d]=%v\n", index, arg)
}
}
}
// flag包基本使用:
// flag包支援的命令列引數型別有bool、int、int64、uint、uint64、float float64、string、duration。
// 指定命令列引數時覆蓋預設命令列引數,不指定命令列引數時使用預設命令列引數
/*
支援的命令列引數格式有以下幾種:
-flag xxx (使用空格,一個-符號)
--flag xxx (使用空格,兩個-符號)
-flag=xxx (使用等號,一個-符號)
--flag=xxx (使用等號,兩個-符號)
其中,布林型別的引數必須使用等號的方式指定。
*/
// flag.Type()
// 需要注意的是,此時name、age、married、delay均為對應型別的指標。
// flag.Type(flag名, 預設值, 幫助資訊) *Type
func flagType() {
name := flag.String("name", "張三", "姓名")
age := flag.Int("age", 18, "年齡")
married := flag.Bool("married", false, "婚否")
delay := flag.Duration("delay", 0, "時間間隔")
flag.Parse()
fmt.Println(flag.Args()) //返回命令列引數後的其他引數,以[]string型別
fmt.Println(flag.NArg()) //返回命令列引數後的其他引數個數
fmt.Println(flag.NFlag()) //返回使用的命令列引數個數
fmt.Println(*name, *age, *married, *delay)
}
// flag.TypeVar()
// 需要注意的是,此時name、age、married、delay均不為對應型別的指標。
// flag.TypeVar(Type指標, flag名, 預設值, 幫助資訊)
func flagTypeVar() {
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, "delay", 0, "時間間隔")
flag.Parse()
fmt.Println(flag.Args()) //返回命令列引數後的其他引數,以[]string型別
fmt.Println(flag.NArg()) //返回命令列引數後的其他引數個數
fmt.Println(flag.NFlag()) //返回使用的命令列引數個數
fmt.Println(name, age, married, delay)
}
func main() {
//argsLen()
//flagType()
flagTypeVar()
}
/*
PS D:\Code\GoCode\hello\16flag> go build main.go
PS D:\Code\GoCode\hello\16flag> .\main.exe -h
Usage of D:\Code\GoCode\hello\16flag\main.exe:
-age int
年齡 (default 18)
-delay duration
時間間隔
-married
婚否
-name string
姓名 (default "張三")
PS D:\Code\GoCode\hello\16flag> .\main.exe -name 劉暢 --age 27 -married=true -delay 10000h0m0s
[]
0
4
劉暢 27 true 10000h0m0s
PS D:\Code\GoCode\hello\16flag> .\main.exe a b c
[a b c]
3
0
張三 18 false 0s
*/
7 log
main.go
package main
import (
"fmt"
"log"
"os"
)
// log
// 無論是軟體開發的除錯階段還是軟體上線之後的執行階段,日誌一直都是非常重要的一個環節,我們也應該養成在程式中記錄日誌的好習慣。
// Go語言內建的log包實現了簡單的日誌服務。
// log common01
// logger會列印每條日誌資訊的日期、時間,預設輸出到系統的標準錯誤。
// Fatal系列函式會在寫入日誌資訊後呼叫os.Exit(1)。Panic系列函式會在寫入日誌資訊後panic。
func logCommon() {
log.Println("這是一條很普通的日誌")
v := "很普通的"
log.Printf("這是一條%s日誌", v)
log.Fatalln("這是一條會觸發fatal的日誌")
//log.Panicln("這是一條會觸發panic的日誌")
}
//配置日誌格式
/*
log標準庫提供瞭如下的flag選項,它們是一系列定義好的常量。
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的初始值
)
*/
func setLogFlag() {
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
}
// 配置日誌字首
func setLogPreFix() {
log.SetPrefix("[goLog]")
}
// 配置日誌輸出位置
func setLogLocation() {
logfile, err := os.OpenFile("./17log/go.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)
}
func main() {
setLogPreFix()
setLogFlag()
setLogLocation()
logCommon()
}
/*
[goLog]2022/03/30 01:08:29.941318 D:/Code/GoCode/hello/17log/main.go:17: 這是一條很普通的日誌
[goLog]2022/03/30 01:08:29.976345 D:/Code/GoCode/hello/17log/main.go:19: 這是一條很普通的日誌
[goLog]2022/03/30 01:08:29.976345 D:/Code/GoCode/hello/17log/main.go:20: 這是一條會觸發fatal的日誌
*/
log_init.go
package main
import (
"fmt"
"log"
"os"
)
//如果你要使用標準的logger,我們通常會把上面的配置操作寫到init函式中。
func init() {
logFile, err := os.OpenFile("./17log/go.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Println("open log file failed, err:", err)
return
}
log.SetPrefix("[goLog]")
log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
log.SetOutput(logFile)
}
func logCommon2() {
log.Println("這是一條很普通的日誌")
v := "很普通的"
log.Printf("這是一條%s日誌", v)
log.Fatalln("這是一條會觸發fatal的日誌")
//log.Panicln("這是一條會觸發panic的日誌")
}
func main() {
logCommon2()
}