加 Golang學習 QQ群共同學習進步成家立業工作 ^-^ 群号:96933959
strings
import "strings"
strings包實作了用于操作字元的簡單函數。
strings.Index("suoning", "n") //3(子串第一次出現的位置,不存在則傳回-1)
strings.LastIndex("suoning", "n") //5(子串最後一次出現的位置,不存在則傳回-1)
strings.Replace("suoning", "ning", "nick", -1) //suonick(替換,n為替換次數,<0替換所有子串)
strings.HasPrefix("suoning", "suo") //true(判斷s是否有字首字元串prefix)
strings.HasSuffix("suoning", "ning") //true(判斷s是否有字尾字元串suffix)
strings.Contains("suoning", "suoni") //true(判斷字元串s是否包含子串substr)
strings.Count("nnnnnn", "n") //6(字元串中有幾個不重複的子串)
strings.Repeat("n", 6) //nnnnnn(傳回count個s串聯的字元串)
strings.ToLower("SuoNing") //suoning(将所有字母都轉為對應的小寫版本的拷貝)
strings.ToUpper("suoning") //SUONING(将所有字母都轉為對應的大寫版本的拷貝)
strings.TrimSpace(" \nsuoning\n ") //suoning(去掉前後端所有空白)
strings.Trim("!!suoning!!", "!") //suoning(将s前後端所有cutset包含的utf-8碼值都去掉的字元串)
strings.TrimLeft("!suoning!", "!") //suoning!(将s前端所有cutset包含的utf-8碼值都去掉的字元串)
strings.TrimRight("!suoning!", "!") //!suoning(将s後端所有cutset包含的utf-8碼值都去掉的字元串)
strings.Fields(" suo ning ") //[suo ning](按照空白分割的多個字元串)
strings.Split(",suo,ning,", ",") //[ suo ning ](去掉s中出現的sep的方式進行分割)
strings.Join([]string{"suo", "ning"}, " ") //suo ning(用sep來拼接為一個字元串)
bytes
import "bytes"
bytes包實作了操作[]byte的常用函數。本包的函數和strings包的函數相當類似。
s1 := []byte("索甯")
s2 := []byte("索")
fmt.Println(bytes.Equal(s1, s2)) //false(切片的内容是否完全相同)
//Runes函數傳回和s等價的[]rune切片。(将utf-8編碼的unicode碼值分别寫入單個rune)
r1 := bytes.Runes(s1)
r2 := bytes.Runes(s2)
fmt.Println(r1) //[32034 23425]
fmt.Println(r2) //[32034]
fmt.Println(r1[0] == r2[0]) //true(可以判斷中文)
strconv
import "strconv"
strconv包實作了基本資料類型和其字元串表示的互相轉換。
//傳回字元串表示的整數值
fmt.Println(strconv.ParseInt("-999", 0, 0)) //-999 <nil>
fmt.Println(strconv.ParseUint("999", 0, 0)) //999 <nil>
fmt.Println(strconv.Atoi("999")) //999 <nil>
//base指定進制(2到36),如果base為0,則會從字元串前置判斷,"0x"是16進制,"0"是8進制,否則是10進制;
//bitSize指定結果必須能無溢出指派的整數類型,0、8、16、32、64 分别代表 int、int8、int16、int32、int64;
//傳回i的base進制的字元串表示
fmt.Println(strconv.FormatInt(-520, 10)) //-520
fmt.Println(strconv.FormatUint(520, 10)) //520
fmt.Println(strconv.Itoa(520)) //520
//base 必須在2到36之間,結果中會使用小寫字母'a'到'z'表示大于10的數字。
//傳回字元串表示的bool值
fmt.Println(strconv.ParseBool("false")) //false <nil>
fmt.Println(strconv.FormatBool(true)) //true
fmt.Println(strconv.AppendBool([]byte{}, true)) //[116 114 117 101]
//它接受1、0、t、f、T、F、true、false、True、False、TRUE、FALSE;否則傳回錯誤。
//傳回字元串表示的bool值
fmt.Println(strconv.ParseFloat("520.1314", 10)) //520.1314 <nil>
fmt.Println(strconv.FormatFloat(520.1314, 'f', 6, 32)) //520.131409
//fmt表示格式:'f'(-ddd.dddd)、'b'(-ddddp±ddd,指數為二進制)、'e'(-d.dddde±dd,十進制指數)、'E'(-d.ddddE±dd,十進制指數)、'g'(指數很大時用'e'格式,否則'f'格式)、'G'(指數很大時用'E'格式,否則'f'格式)。
//prec控制精度(排除指數部分):對'f'、'e'、'E',它表示小數點後的數字個數;對'g'、'G',它控制總的數字個數。如果prec 為-1,則代表使用最少數量的、但又必需的數字來表示f。
//bitSize表示f的來源類型(32:float32、64:float64),會據此進行舍入。
time
import "time"
time包提供了時間的顯示和測量用的函數。月曆的計算采用的是公曆。
fmt.Println(time.Now()) //2017-08-03 22:35:36.45766459 +0800 CST
fmt.Println(time.Now().Unix()) //時間戳1501771053
fmt.Println(time.Sunday) //Sunday
fmt.Println(time.Stamp) //Jan _2 15:04:05
fmt.Println(time.Date(2008, time.November, 11, 23, 0, 0, 0, time.UTC))
//2008-11-11 23:00:00 +0000 UTC
//格式化輸出
now := time.Now()
fmt.Println(now.Format("02/1/2006 15:04:05")) //03/8/2017 22:37:58
fmt.Println(now.Format("2006/02/1 15:04")) //2017/03/8 22:37
fmt.Println(now.Format("2006-1-02 15:04:05")) //2017-8-03 22:37:58
m, _ := time.ParseDuration("-10m") //10分鐘前
fmt.Println(now.Add(m)) //2017-08-03 22:34:55.810202385 +0800 CST
d, _ := time.ParseDuration("-24h") //1天前
fmt.Println(now.Add(d)) //2017-08-02 22:46:28.742383801 +0800 CST
hh, _ := time.ParseDuration("1h") //1小時後
fmt.Println(now.Add(hh)) //2017-08-03 23:47:21.458974014 +0800 CST
time.Sleep(time.Second) //睡一秒
//定時器
t := time.NewTicker(time.Second)
for v := range t.C { //每一秒執行一次, 這是個死循環
fmt.Println(v) //2017-08-03 22:53:13.849203492 +0800 CST
}
t.Stop()
math/rand
import "math/rand"
rand包實作了僞随機數生成器。
随機數從資源生成。包水準的函數都使用的預設的公共資源。該資源會在程式每次運作時都産生确定的序列。如果需要每次運作産生不同的序列,應使用Seed函數進行初始化。預設資源可以安全的用于多go程并發。
func init() {
rand.Seed(time.Now().UnixNano()) //使用給定的seed來初始化生成器到一個确定的狀态。
}
func main() {
fmt.Println(rand.Int()) //9153536921449289609(傳回一個非負的僞随機int值)
fmt.Println(rand.Int31()) //2037735069(傳回一個int32類型的非負的31位僞随機數)
fmt.Println(rand.Int63()) //1132646811815532030(傳回一個int64類型的非負的63位僞随機數)
fmt.Println(rand.Intn(100)) //95(取值範圍在[0,n)的僞随機int值,n<=0會panic)
fmt.Println(rand.Float32()) //0.09178123(取值範圍在[0.0, 1.0)的僞随機float32值)
fmt.Println(rand.Perm(5)) //[0 4 1 2 3](有n個元素的,[0,n)範圍内整數的僞随機排列的切片)
}
os
import "os"
os包提供了作業系統函數的不依賴平台的接口。設計為Unix風格的,雖然錯誤處理是go風格的;失敗的調用會傳回錯誤值而非錯誤碼。通常錯誤值裡包含更多資訊。
fmt.Println(os.Hostname()) //bogon <nil>(傳回核心提供的主機名)
fmt.Println(os.Getpagesize()) //4096(傳回底層的系統記憶體頁的尺寸)
fmt.Println(os.Environ()) //(環境變量的格式為"key=value"的字元串的切片拷貝)
fmt.Println(os.Getenv("GOPATH")) //(名為key的環境變量的值,不存在傳回空)
fmt.Println(os.Setenv("Name", "Nick")) //(設定名為key的環境變量)
os.Clearenv() //(删除所有環境變量)
os.Exit(0) //(以給出的狀态碼code退出,程式會立刻終止,defer的函數不會被執行)
fmt.Println(os.Getuid()) //501(調用者的使用者ID)
fmt.Println(os.Geteuid()) //501(調用者的有效使用者ID)
fmt.Println(os.Getgid()) //20(調用者的組ID)
fmt.Println(os.Getegid()) //20(調用者的有效組ID)
fmt.Println(os.Getgroups()) //[20 701 12 61 79 80 81 ...](調用者所屬的所有使用者組的組ID)
fmt.Println(os.Getpid()) //62027(調用者所在程序的程序ID)
fmt.Println(os.Getppid()) //62020(調用者所在程序的父程序的程序ID)
fmt.Println(os.Getwd()) //傳回一個對應目前工作目錄的根路徑
os.Chdir("/tmp/") //将目前工作目錄修改為dir指定的目錄
os.Mkdir("/tmp/test", 0666) //用指定的權限和名稱建立一個目錄
os.MkdirAll("/tmp/test1/test2/test3", 0666) //使用指定的權限和名稱建立一個目錄,遞歸上級目錄
os.Rename("/tmp/test", "/tmp/test1/testNew") //修改一個檔案的名字,移動一個檔案
os.Remove("/tmp/test1/test2/test3") //删除name指定的檔案或目錄
os.RemoveAll("/tmp/test1/") //删除path指定的檔案
os.Create("/tmp/test") //0666,建立檔案,存在會清空
os.Open("/tmp/test") //O_RDONLY,打開一個檔案
os.OpenFile("/tmp/test", os.O_CREATE|os.O_WRONLY, 0666)
Args保管了指令行參數,第一個是程式名。
fmt
import "fmt"
mt包實作了類似C語言printf和scanf的格式化I/O。格式化動作('verb')源自C語言但更簡單。
通用:
%v 值的預設格式表示
%+v 類似%v,但輸出結構體時會添加字段名
%#v 值的Go文法表示
%T 值的類型的Go文法表示
%% 百分号
布爾值:
%t 單詞true或false
整數:
%b 表示為二進制
%c 該值對應的unicode碼值
%d 表示為十進制
%o 表示為八進制
%q 該值對應的單引号括起來的go文法字元字面值,必要時會采用安全的轉義表示
%x 表示為十六進制,使用a-f
%X 表示為十六進制,使用A-F
%U 表示為Unicode格式:U+1234,等價于"U+%04X"
浮點數與複數的兩個組分:
%b 無小數部分、二進制指數的科學計數法,如-123456p-78;參見strconv.FormatFloat
%e 科學計數法,如-1234.456e+78
%E 科學計數法,如-1234.456E+78
%f 有小數部分但無指數部分,如123.456
%F 等價于%f
%g 根據實際情況采用%e或%f格式(以獲得更簡潔、準确的輸出)
%G 根據實際情況采用%E或%F格式(以獲得更簡潔、準确的輸出)
%f: 預設寬度,預設精度
%9f 寬度9,預設精度
%.2f 預設寬度,精度2
%9.2f 寬度9,精度2
%9.f 寬度9,精度0
字元串和[]byte:
%s 直接輸出字元串或者[]byte
%q 該值對應的雙引号括起來的go文法字元串字面值,必要時會采用安全的轉義表示
%x 每個位元組用兩字元十六進制數表示(使用a-f)
%X 每個位元組用兩字元十六進制數表示(使用A-F)
指針:
%p 表示為十六進制,并加上前導的0x
errors
import "errors"
errors包實作了建立錯誤值的函數。
使用字元串建立一個錯誤,請類比fmt包的Errorf方法,差不多可以認為是New(fmt.Sprintf(...))。
err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
fmt.Print(err) //emit macho dwarf: elf header corrupted
}
const name, id = "bimmler", 17
err := fmt.Errorf("user %q (id %d) not found", name, id)
if err != nil {
fmt.Print(err) //user "bimmler" (id 17) not found
}
json
import "encoding/json"
json包實作了json對象的編解碼。Marshal、Unmarshal函數。
Marshal函數傳回v的json編碼:
type ColorGroup struct {
ID int
Name string
Colors []string
}
group := ColorGroup{
ID: 1,
Name: "Reds",
Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
}
b, err := json.Marshal(group)
if err != nil {
fmt.Println("error:", err)
}
os.Stdout.Write(b)
//{"ID":1,"Name":"Reds","Colors":["Crimson","Red","Ruby","Maroon"]}
Unmarshal函數解析json編碼的資料并将結果存入v指向的值:
var jsonBlob = []byte(`[
{"Name": "Platypus", "Order": "Monotremata"},
{"Name": "Quoll", "Order": "Dasyuromorphia"}
]`)
type Animal struct {
Name string
Order string
}
var animals []Animal
err := json.Unmarshal(jsonBlob, &animals)
if err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", animals)
//[{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}]
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"userName"`
Age int
}
func main() {
u1 := &User{Name: "nick", Age: 18}
u1Str, err := json.Marshal(u1)
fmt.Println(err)
fmt.Println(u1Str)
var u User
err = json.Unmarshal([]byte(u1Str), &u)
fmt.Println(err)
fmt.Println(u)
}
struct tag 使用:
// 字段被本包忽略
Field int `json:"-"`
// 字段在json裡的鍵為"myName"
Field int `json:"myName"`
// 字段在json裡的鍵為"myName"且如果字段為空值将在對象中省略掉
Field int `json:"myName,omitempty"`
// 字段在json裡的鍵為"Field"(預設值),但如果字段為空值會跳過;注意前導的逗号
Field int `json:",omitempty"`
reflect
flag
import "flag"
flag包實作了指令行參數的解析。
func main() {
var confPath string
var port int
var b bool
flag.StringVar(&confPath, "conf", "", "input config path.")
flag.IntVar(&port, "p", 8000, "input port.")
flag.BoolVar(&b, "b", false, "input bool.")
flag.Parse() //注冊
fmt.Println("config path: ", confPath)
fmt.Println("port: ", port)
fmt.Println("bool: ", b)
}
$ go build -o bin/test go_dev/args/main
$ bin/test -conf "/tmp/config" -p 9006 -b true
config path: /tmp/config
port: 9006
bool: true
context
一、傳遞全局變量
func process(ctx context.Context) {
ret, ok := ctx.Value("trace_id").(int)
if !ok {
ret = 123456
}
fmt.Println(ret) //111111
s, _ := ctx.Value("name").(string)
fmt.Println(s) //suoning
}
func main() {
ctx := context.WithValue(context.Background(), "name", "suoning")
ctx = context.WithValue(ctx, "trace_id", 111111)
process(ctx)
}
func add(ctx context.Context, a, b int) int {
traceId := ctx.Value("trace_id").(string)
fmt.Printf("trace_id:%v\n", traceId)
return a + b
}
func calc(ctx context.Context, a, b int) int {
traceId := ctx.Value("trace_id").(string)
fmt.Printf("trace_id:%v\n", traceId)
return add(ctx, a, b)
}
func main() {
ctx := context.WithValue(context.Background(), "trace_id", "123456")
s := calc(ctx, 500, 20)
fmt.Println(s)
}
二、Goroutine Timeout
package main
import (
"net/http"
"context"
"time"
"fmt"
"io/ioutil"
)
type Result struct {
r *http.Response
err error
}
func process() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
tr := &http.Transport{}
client := &http.Client{Transport: tr}
c := make(chan Result, 1)
req, err := http.NewRequest("GET", "http://www.google.com", nil)
if err != nil {
fmt.Println("http NewRequest failed, err:", err)
return
}
go func() {
resp, err := client.Do(req)
pack := Result{r: resp, err: err}
c <- pack
}()
select {
case <-ctx.Done():
tr.CancelRequest(req)
res := <-c
fmt.Println("Timeout, err:", res.err)
case res := <-c:
defer res.r.Body.Close()
out, _ := ioutil.ReadAll(res.r.Body)
fmt.Printf("Server Response: %s", out)
}
return
}
func main() {
process()
}
sync
等待一組Goroutine傳回
package main
import (
"sync"
"fmt"
"time"
)
func calc(w *sync.WaitGroup, i int) {
fmt.Println("calc: ", i)
time.Sleep(time.Second)
w.Done()
}
func main() {
wg := sync.WaitGroup{}
for i:=0; i<10; i++ {
wg.Add(1)
go calc(&wg, i)
}
wg.Wait()
fmt.Println("all goroutine finish")
}