加 Golang學習 QQ羣共同窗習進步成家立業工做 ^-^ 羣號:96933959html
import "strings"
前端
strings包實現了用於操做字符的簡單函數。java
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來拼接爲一個字符串)
import "bytes"
node
bytes包實現了操做[]byte的經常使用函數。本包的函數和strings包的函數至關相似。git
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(能夠判斷中文)
import "strconv"
github
strconv包實現了基本數據類型和其字符串表示的相互轉換。golang
//返回字符串表示的整數值 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、八、1六、3二、64 分別表明 int、int八、int1六、int3二、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] //它接受一、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:float3二、64:float64),會據此進行舍入。
import "time"
json
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()
// 獲取到明天凌晨秒數 t := time.Now() t2 := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()).AddDate(0, 0, 1) fmt.Println(time.Second*time.Duration(t2.Unix()-t.Unix()))
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)範圍內整數的僞隨機排列的切片) }
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保管了命令行參數,第一個是程序名。
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
//前置補0 fmt.Printf("%03d", 22) fmt.Println("") fmt.Printf("%0*d", 3, 2)
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 }
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"`
time時間處理
type TimeBirthday time.Time func (obj TimeBirthday) MarshalJSON() ([]byte, error) { seconds := time.Time(obj).Format("2006-01-02") return []byte(fmt.Sprintf(`"%s"`, seconds)), nil } type Account struct { Birthday TimeBirthday `json:"birthday"` LastLoginTime time.Time `json:"-"` }
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
1、傳遞全局變量
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) }
2、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() }
等待一組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") }
redirect := "http://cm-wzry.cmcm.com/spread/jump?uri=http%3a%2f%2fa.app.qq.com%2fo%2fsimple.jsp%3fpkgname%3dcom.cmcm.gamemaster%26f%3d6" // 編碼 encodeurl := url.QueryEscape(redirect) fmt.Println(encodeurl) // 解碼 decodeurl, err := url.QueryUnescape(encodeurl) if err != nil { panic(err) } fmt.Println(decodeurl)
// 檢測中文字符
package main import ( "fmt" "regexp" ) func main() { str := "Nick要脫單" var hzRegexp = regexp.MustCompile("^[\u4e00-\u9fa5]$") fmt.Println(hzRegexp.MatchString(str)) }
// 中文截取
string([]rune(Text)[:Max])
Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) dst 繪圖的背景圖。 r 是背景圖的繪圖區域 src 是要繪製的圖 sp 是 src 對應的繪圖開始點(繪製的大小 r變量定義了) mask 是繪圖時用的蒙版,控制替換圖片的方式。 mp 是繪圖時蒙版開始點(繪製的大小 r變量定義了) // op Op is a Porter-Duff compositing operator. 參考文章:"http://blog.csdn.net/ison81/article/details/5468763" http://blog.csdn.net/ison81/article/details/5468763 // Porter-Duff 等式12種規則能夠看這篇博客:"http://www.blogjava.net/onedaylover/archive/2008/01/16/175675.html" http://www.blogjava.net/onedaylover/archive/2008/01/16/175675.html
// 截取圖片的一部分 // in out 圖片絕對路徑 ("/data/zyn/%04d.jpg")("/data/zyn.jpeg") // sx sy 開始截取點 // x1 y1 輸出圖片的大小 func CapturePortion(in, out string, sx, sy int, x1, y1 int, log *zap.SugaredLogger) error { file, err := os.Create(out) if err != nil { log.Errorf("os.Create(out) out(%v) err(%v)", out, err) return err } defer file.Close() file1, err := os.Open(in) if err != nil { log.Errorf("os.Open(in) in(%v) err(%v)", in, err) return err } defer file1.Close() img, err := jpeg.Decode(file1) if err != nil { log.Errorf("peg.Decode(file1) in(%v) err(%v)", in, err) return err } jpg := image.NewRGBA(image.Rect(0, 0, x1, y1)) draw.Draw(jpg, img.Bounds(), img, image.Pt(sx, sy), draw.Src) //截取圖片的一部分 if err := jpeg.Encode(file, jpg, nil); err != nil { log.Errorf("jpeg.Encode(file, jpg, nil) out(%v) err(%v)", out, err) return err } return nil }
import ( "errors" z "github.com/nutzam/zgo" "github.com/BurntSushi/graphics-go/graphics" "go.uber.org/zap" ) // 修改圖片像素 //x1 := 720 //y1 := 1280 func PixelModification(srcPath string, outPath string, x1, y1 int, log *zap.SugaredLogger) error { // 打開圖片 src, err := z.ImageJPEG(srcPath) // 打開失敗 if err != nil { log.Errorf("z.ImageJPEG(srcPath) srcPath(%v) err(%v)", srcPath, err) return err } // 建立一張圖片 dst := z.ImageRGBA(x1, y1) if dst == nil { // 異常返回 log.Errorf("z.ImageRGBA(x1, y1) x1(%v) y1(%v) srcPath(%v)", x1, y1, srcPath) return errors.New("z.ImageRGBA eq nil") } // 將src圖片,縮小,放大,拉伸到dst圖片大小 if err := graphics.Scale(dst, src); err != nil { log.Errorf("graphics.Scale(dst, src) x1(%v) y1(%v) srcPath(%v) err(%v)", x1, y1, srcPath, err) return err } if err := z.ImageEncodeJPEG(outPath, dst, 50); err != nil { log.Errorf("z.ImageEncodeJPEG(outPath, dst, 50) x1(%v) y1(%v) srcPath(%v) outPath(%v) err(%v)", x1, y1, srcPath, outPath, err) return err } return nil }
package main import ( "fmt" "image" "image/draw" "image/jpeg" "image/png" "os" ) func main() { file, err := os.Create("dst.jpg") if err != nil { fmt.Println(err) } defer file.Close() file1, err := os.Open("qr2tt.png") if err != nil { fmt.Println(err) } defer file1.Close() img, _ := png.Decode(file1) file2, err := os.Open("/Users/suoning/Documents/圖片/F1.jpeg") if err != nil { fmt.Println(err) } defer file2.Close() img2, _ := jpeg.Decode(file2) //jpg := image.NewRGBA(image.Rect(0, 0, 2976, 3968)) jpg := image.NewRGBA(image.Rect(0, 0, 2976, 3968)) draw.Draw(jpg, jpg.Bounds(), img2, img2.Bounds().Min, draw.Over) //首先將一個圖片信息存入jpg draw.Draw(jpg, jpg.Bounds(), img, img.Bounds().Min.Sub(image.Pt(800, 2300)), draw.Over) //將另一張圖片信息存入jpg // draw.DrawMask(jpg, jpg.Bounds(), img, img.Bounds().Min, img2, img2.Bounds().Min, draw.Src) // 利用這種方法不可以將兩個圖片直接合成?目前尚不知道緣由。 jpeg.Encode(file, jpg, nil) }
func GetCert(log *zap.SugaredLogger) (*tls.Certificate, error) { cert, err := tls.LoadX509KeyPair(CrtPemPath, KeyPemPath) if err != nil { log.Errorf("tls.LoadX509KeyPair() crt(%v) key(%v) err(%v)", CrtPemPath, KeyPemPath, err) return nil, err } return &cert, nil }
pkcs12 轉 pem
openssl pkcs12 -in path.p12 -out newfile.crt.pem -clcerts -nokeys -passin 'pass:password' openssl pkcs12 -in path.p12 -out newfile.key.pem -nocerts -nodes -passin 'pass:password'
證書請求
client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ Certificates: []tls.Certificate{*cert}, }, }, }