├── .gitignore ├── README.md ├── basic ├── 01test │ ├── funcs.go │ └── funcs_test.go ├── 02error │ └── error-unwrap.go ├── 03syntax │ ├── chan │ │ ├── errchan │ │ │ └── main.go │ │ └── main.go │ ├── func │ │ └── main.go │ ├── goroutine │ │ └── main.go │ ├── import │ │ ├── a │ │ │ └── a.go │ │ ├── b │ │ │ └── b.go │ │ └── main.go │ ├── memory │ │ └── main.go │ ├── nil │ │ └── main.go │ ├── pkgexported │ │ ├── main.go │ │ └── pkg1 │ │ │ └── pkg1.go │ ├── range │ │ └── range.go │ └── switch │ │ └── main.go ├── 04pprof │ └── main.go ├── 05panic │ └── panic.go ├── 06memory │ └── wrong_done │ │ └── wrong_done.go ├── 07marshal │ ├── unmarshal.go │ └── unmarshal_test.go ├── 08goroutine │ └── waitgroup │ │ └── waitgroup.go ├── 09basicpkg │ ├── file │ │ └── file.go │ ├── json │ │ └── json.go │ ├── reflect │ │ └── reflect.go │ ├── signal │ │ └── signal.go │ ├── syncmap │ │ └── syncmap.go │ └── timeticker │ │ └── timeticker.go ├── 10gomod │ └── main.go ├── 11debug │ └── debug.go ├── 12convert │ └── convert.go ├── 13httpserver │ ├── 01default │ │ └── main.go │ ├── 02defserver │ │ └── main.go │ ├── 03mux │ │ └── main.go │ └── httpserver.go ├── 14pmisc │ └── main.go ├── 16const │ └── iota.go ├── 17time │ └── time.go ├── 18arith │ └── main.go └── 19slice │ └── slice.go ├── cadvisor ├── .gitignore └── main.go ├── envoydev ├── README.md └── xds │ ├── .gitignore │ ├── envoy-docker-run │ ├── envoy-0-default.yaml │ ├── envoy-0-example.yaml │ ├── envoy-1-ads-with-xds.yaml │ ├── envoy-1-ads.yaml │ ├── envoy-1-static.yaml │ ├── envoy-1-xds.yaml │ ├── envoy-to-grpc-svc.yaml │ ├── envoy-to-tcp.yaml │ ├── log │ │ └── admin_access.log │ └── run.sh │ └── xds.go ├── etcdclientv3 ├── crud │ └── crud.go └── election │ └── election.go ├── ginusage ├── 01quickstart │ └── quickstart.go ├── 02router │ └── router.go ├── 03grouprouter │ └── grouprouter.go ├── 04paraminquery │ └── paraminquery.go ├── 05paraminheader │ └── paraminheader.go ├── 06paraminpath │ └── paraminpath.go ├── 07parampost │ ├── form │ │ └── postform.go │ └── json_and_others │ │ └── json_and_others.go ├── 08middleware │ └── middleware.go ├── 08response │ └── response.go ├── 09log │ └── logset.go ├── 09upload │ └── upload.go ├── 11validator │ └── validator.go ├── 12render │ └── render.go ├── 13serving │ ├── serving.go │ ├── static │ │ ├── 1.txt │ │ ├── file.txt │ │ └── static │ └── static2 │ │ ├── 2.txt │ │ └── static2 ├── 14render │ ├── render.go │ └── templates │ │ ├── index.tmpl │ │ └── posts │ │ └── index.tmpl ├── 15goroutine │ └── goroutine.go ├── 16tls │ └── lets.go ├── 17multiserver │ └── multiserver.go ├── 18graceful │ └── graceful.go ├── 19singlebinary │ ├── Makefile │ ├── assets.go │ ├── html │ │ └── index.tmpl │ └── singlebinary.go ├── 20http2 │ ├── assets │ │ └── app.js │ └── http2.go ├── 21cookie │ └── cookie.go └── 22test │ ├── test.go │ └── test_test.go ├── go.mod ├── go.sum ├── gormusage ├── 01connect │ └── connect.go ├── 02model │ └── models.go ├── 03crud │ └── crud.go └── common │ ├── student.go │ └── user.go ├── k8sclient ├── beartoken │ └── main.go ├── clientset │ └── clientset.go ├── incluster │ ├── Dockerfile │ ├── Makefile │ ├── deploy.yaml │ └── incluster.go ├── informer │ └── informer.go ├── podinfo │ └── podinfo.go └── restclient │ └── restclient.go └── opentracingusage ├── 00-quickstart └── quickstart.go ├── 01-httptrace └── httpreq.go └── common.go /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | .vscode/ 4 | *.swp 5 | *.iml 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go 代码片段 2 | 3 | ## 说明 4 | 5 | 这里是了解 go 语言细节或者一些标准库、SDK 的使用方法时,随手写的一些代码片段。 6 | 7 | ## 目录 8 | 9 | ▸ [stdpackage/](stdpkg/): Go 标准库的使用 10 | 11 | ▸ [syntax/](./syntax/): Go 语法细节探索 12 | 13 | ▸ [etcdclientv3/](./etcdclientv3/): etcdclientv3 的使用 14 | 15 | * [Etcd 的 go sdk 的使用方法:etcd/clientv3](https://www.lijiaocn.com/%E7%BC%96%E7%A8%8B/2019/06/19/etcd-go-sdk-clientv3-usage.html) 16 | 17 | ▸ [k8sclient/](./k8sclient/): Kubernete 的 client-go 的使用 18 | 19 | ▸ [envoydev/](./envoydev/): Envoy 开发,主要是控制平面开发 20 | 21 | ▸ [ginusage/](./ginusage/): Web 框架 gin 的使用 22 | -------------------------------------------------------------------------------- /basic/01test/funcs.go: -------------------------------------------------------------------------------- 1 | package testcase 2 | 3 | func SumSlice(nums []int) int { 4 | sum := 0 5 | for _, v := range nums { 6 | sum = sum + v 7 | } 8 | return sum 9 | } 10 | 11 | func SumArray(nums [10]int) int { 12 | sum := 0 13 | for _, v := range nums { 14 | sum = sum + v 15 | } 16 | return sum 17 | } 18 | 19 | func SumArrayP(nums *[10]int) int { 20 | sum := 0 21 | for _, v := range nums { 22 | sum = sum + v 23 | } 24 | return sum 25 | } 26 | -------------------------------------------------------------------------------- /basic/01test/funcs_test.go: -------------------------------------------------------------------------------- 1 | package testcase 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSumSlice(t *testing.T) { 8 | arrays := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 9 | expect := 45 10 | sum := SumSlice(arrays[:]) 11 | if sum != expect { 12 | t.Errorf("result is %d (should be %d)", sum, expect) 13 | } 14 | } 15 | 16 | func BenchmarkSumSlice(b *testing.B) { 17 | arrays := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 18 | s := arrays[:] 19 | for i := 0; i < b.N; i++ { 20 | SumSlice(s) 21 | } 22 | } 23 | 24 | func BenchmarkSumArray(b *testing.B) { 25 | arrays := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 26 | for i := 0; i < b.N; i++ { 27 | SumArray(arrays) 28 | } 29 | } 30 | 31 | func BenchmarkSumArrayP(b *testing.B) { 32 | arrays := [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 33 | arraysp := &arrays 34 | for i := 0; i < b.N; i++ { 35 | SumArrayP(arraysp) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /basic/02error/error-unwrap.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/12/03 14:31:00 Change: 2019/12/03 14:42:06 2 | // FileName: error-unwrap.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "errors" 11 | ) 12 | 13 | type QueryError struct { 14 | Query string 15 | Err error 16 | } 17 | 18 | func (e *QueryError) Error() string { 19 | return e.Query + ": " + e.Err.Error() 20 | } 21 | 22 | func (e *QueryError) Unwrap() error { 23 | return e.Err 24 | } 25 | 26 | func FunC() error { 27 | return errors.New("err in Function C") 28 | } 29 | 30 | func FunB() error { 31 | err := FunC() 32 | if err != nil { 33 | return &QueryError{Query: "query error", Err: err} 34 | } 35 | return nil 36 | } 37 | 38 | func main() { 39 | err := FunB() 40 | if err != nil { 41 | println(err.Error()) 42 | if inter := errors.Unwrap(err); inter != nil { 43 | println(inter.Error()) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /basic/03syntax/chan/errchan/main.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/08 17:20:00 Change: 2019/07/08 17:28:50 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "errors" 11 | "fmt" 12 | ) 13 | 14 | func send(errChan chan<- error) { 15 | for i := 0; i < 3; i++ { 16 | errChan <- errors.New("hello") 17 | } 18 | } 19 | 20 | func main() { 21 | c := make(chan error) 22 | go send(c) 23 | for { 24 | err := <-c 25 | fmt.Println(err.Error()) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /basic/03syntax/chan/main.go: -------------------------------------------------------------------------------- 1 | // Create: 2018/08/28 19:03:00 Change: 2019/07/08 17:20:13 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2018 lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "time" 11 | ) 12 | 13 | type Child func(input string) 14 | type Child2 func(input string, c chan string) 15 | 16 | func parent2(c chan string) Child2 { 17 | f := func(str string, c chan string) { 18 | for { 19 | c <- str 20 | time.Sleep(1 * time.Second) 21 | } 22 | } 23 | return f 24 | } 25 | 26 | func parent(c chan<- string) Child { 27 | f := func(str string) { 28 | for { 29 | c <- str 30 | time.Sleep(1 * time.Second) 31 | } 32 | } 33 | return f 34 | } 35 | 36 | func main() { 37 | 38 | c := make(chan string, 10) 39 | child := parent(c) 40 | go child("child1") 41 | 42 | // child2 := parent2(c) 43 | // go child2("child1", c) 44 | 45 | time.Sleep(5 * time.Second) 46 | println(len(c)) 47 | 48 | for { 49 | select { 50 | case v := <-c: 51 | println(v) 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /basic/03syntax/func/main.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/04 17:19:00 Change: 2019/07/04 17:19:52 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | func name(params string) { 10 | println("abc") 11 | } 12 | 13 | func main() { 14 | name("abc") 15 | } 16 | -------------------------------------------------------------------------------- /basic/03syntax/goroutine/main.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/01 14:52:00 Change: 2019/07/01 15:06:04 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "time" 11 | ) 12 | 13 | func SubRoute() { 14 | ticker := time.NewTicker(1 * time.Second) 15 | go func() { 16 | for { 17 | select { 18 | case <-ticker.C: 19 | println("1") 20 | } 21 | } 22 | }() 23 | } 24 | 25 | func main() { 26 | SubRoute() 27 | time.Sleep(10 * time.Second) 28 | } 29 | -------------------------------------------------------------------------------- /basic/03syntax/import/a/a.go: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | import ( 4 | "lijiaocn.com/gocode/import/b" 5 | ) 6 | 7 | func AFunc() { 8 | b.AFunc() 9 | println("AFunc") 10 | } 11 | -------------------------------------------------------------------------------- /basic/03syntax/import/b/b.go: -------------------------------------------------------------------------------- 1 | package b 2 | 3 | import ( 4 | "lijiaocn.com/gocode/import/a" 5 | ) 6 | 7 | func BFunc() { 8 | a.AFunc() 9 | println("AFunc") 10 | } 11 | -------------------------------------------------------------------------------- /basic/03syntax/import/main.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/03 15:42:00 Change: 2019/07/03 15:45:29 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "lijiaocn.com/gocode/import/a" 11 | "lijiaocn.com/gocode/import/b" 12 | ) 13 | 14 | func main() { 15 | a.Afunc() 16 | b.Bfunc() 17 | } 18 | -------------------------------------------------------------------------------- /basic/03syntax/memory/main.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/03 17:14:00 Change: 2019/07/03 19:30:32 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | func func2(eles *[]*int) { 10 | for i := 0; i < 10; i++ { 11 | j := i 12 | *eles = append(*eles, &j) 13 | } 14 | } 15 | 16 | func main() { 17 | var eles1 []*int 18 | for i := 0; i < 10; i++ { 19 | j := i 20 | eles1 = append(eles1, &j) 21 | } 22 | 23 | for _, v := range eles1 { 24 | println(v, ":", *v) 25 | } 26 | 27 | println("eles2") 28 | var eles2 []*int 29 | func2(&eles2) 30 | for _, v := range eles2 { 31 | println(v, ":", *v) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /basic/03syntax/nil/main.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/05 11:04:00 Change: 2019/07/05 11:07:18 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | type A struct { 10 | A []string 11 | } 12 | 13 | func main() { 14 | a := A{} 15 | if a.A == nil { 16 | println("is nil") 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /basic/03syntax/pkgexported/main.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/06/12 15:30:00 Change: 2019/06/27 11:01:23 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import "lijiaocn.com/gocode/pkgexported/pkg1" 10 | 11 | func main() { 12 | // 导出的 Struct 类型可用 13 | println("1") 14 | var v1 pkg1.ExportedStruct 15 | println(v1.ExportedField) 16 | // 未导出的 Struct 类型不可用 17 | // var v2 pkg1.unexportedStruct // wrong 18 | 19 | // 导出的变量可用 20 | println("2") 21 | v1 = pkg1.ExportedVar 22 | // 未导出的变量不可用 23 | // v2 = pkg1.unexportedVar 24 | 25 | // 导出的变量的导出的 filed 可以访问 26 | println("3") 27 | println(pkg1.ExportedVar.ExportedField) 28 | // 导出的变量的未导出的 filed 不可以访问 29 | // println(pkg1.ExportedVar.unexportedField) //wrong 30 | 31 | // 导出的变量的导出的方法可用 32 | println("4") 33 | pkg1.ExportedVar.ExportedMethod() 34 | // 导出的变量的未导出的方法不可用 35 | // pkg1.ExportedVar.unexportedMethod() 36 | 37 | // 导出的函数可用 38 | println("5") 39 | pkg1.ExportedFunc() 40 | // 未导出的函数不可用 41 | // pkg1.unexportedFunc() 42 | 43 | // 未导出的函数可以通过导出的函数获得 44 | println("6") 45 | unFunc := pkg1.ReturnUnexporteFunc() 46 | unFunc() 47 | } 48 | -------------------------------------------------------------------------------- /basic/03syntax/pkgexported/pkg1/pkg1.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/06/12 15:33:00 Change: 2019/06/12 15:35:53 2 | // FileName: pkg1.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package pkg1 8 | 9 | //[Exported identifiers](https://golang.org/ref/spec#Exported_identifiers) 10 | // 11 | //An identifier may be exported to permit access to it from another package. An identifier is exported if both: 12 | // 13 | //1. the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); 14 | //2. the identifier is declared in the package block or it is a field name or method name. 15 | // 16 | //All other identifiers are not exported. 17 | 18 | //导出的变量 19 | var ExportedVar ExportedStruct 20 | 21 | //不导出的变量 22 | var unexportedVar unexportedStruct 23 | 24 | //导出的函数 25 | func ExportedFunc() { 26 | println("exported func") 27 | } 28 | 29 | //不导出的函数 30 | func unexportedFunc() { 31 | println("unexported func") 32 | } 33 | 34 | //导出的 Struct 类型 35 | type ExportedStruct struct { 36 | unexportedField string //未导出的 field 37 | ExportedField string //导出的 field 38 | } 39 | 40 | //不导出的 Struct 类型 41 | type unexportedStruct struct { 42 | unexportedField string //未导出的 field 43 | ExportedField string //导出的 field 44 | } 45 | 46 | //导出的 Struct 的方法 47 | func (s ExportedStruct) ExportedMethod() { 48 | println("exported method") 49 | } 50 | 51 | //不导出的 Struct 的方法 52 | func (s ExportedStruct) unexportedMethod() { 53 | println("unexported method") 54 | } 55 | 56 | func ReturnUnexporteFunc() func() { 57 | return unexportedFunc 58 | } 59 | 60 | func init() { 61 | // 在 Package 内部,导出/未导出的变量、导出/未导出的 Struct 类型都可以使用 62 | ExportedVar = ExportedStruct{ 63 | unexportedField: "unexported field", 64 | ExportedField: "exported field", 65 | } 66 | 67 | unexportedVar = unexportedStruct{ 68 | unexportedField: "unexported field", 69 | ExportedField: "exported field", 70 | } 71 | 72 | // 未导出的 Struct 的未导出的 filed 可以使用 73 | unexportedVar.unexportedField = "unexported field" 74 | } 75 | -------------------------------------------------------------------------------- /basic/03syntax/range/range.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var List []string 6 | 7 | func init() { 8 | List = []string{ 9 | "a", 10 | "b", 11 | "c", 12 | } 13 | } 14 | 15 | func main() { 16 | list := make([]int, 10) 17 | for i, v := range list { 18 | copyv := v 19 | fmt.Printf("i=%d v=%d copyv=%d\n", i, &v, ©v) 20 | } 21 | 22 | for i, v := range List { 23 | copyv := v 24 | fmt.Printf("i=%d v=%s copyv=%d\n", i, v, ©v) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /basic/03syntax/switch/main.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/03 19:30:00 Change: 2019/07/08 17:48:03 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | func main() { 10 | i := 1 11 | switch i { 12 | case 1: 13 | fallthrough 14 | case 2: 15 | println("ok") 16 | } 17 | 18 | str := "abc" 19 | switch str { 20 | case "123": 21 | println("123") 22 | case "abc": 23 | println("abc") 24 | } 25 | 26 | str1 := "abc" 27 | switch str { 28 | case "123": 29 | println("123") 30 | case str1: 31 | println("abc") 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /basic/04pprof/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | _ "net/http/pprof" 8 | "time" 9 | ) 10 | 11 | func Write(num int, c chan int) { 12 | for { 13 | c <- num 14 | } 15 | } 16 | 17 | func main() { 18 | go func() { 19 | log.Println(http.ListenAndServe("localhost:6060", nil)) 20 | }() 21 | 22 | c := make(chan int) 23 | go Write(10, c) 24 | go Write(20, c) 25 | 26 | for { 27 | select { 28 | case v := <-c: 29 | fmt.Printf("receive %d\n", v) 30 | time.Sleep(2 * time.Second) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /basic/05panic/panic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | _ "net/http/pprof" 8 | "time" 9 | ) 10 | 11 | func Write(num int, c chan int) { 12 | defer func() { 13 | if r := recover(); r != nil { 14 | fmt.Println("recover in ", r) 15 | } 16 | }() 17 | for { 18 | c <- num 19 | panic(fmt.Sprintf("func input: %d", num)) 20 | } 21 | } 22 | 23 | func main() { 24 | go func() { 25 | log.Println(http.ListenAndServe("localhost:6060", nil)) 26 | }() 27 | 28 | c := make(chan int) 29 | go Write(10, c) 30 | go Write(20, c) 31 | 32 | for { 33 | select { 34 | case v := <-c: 35 | fmt.Printf("receive %d\n", v) 36 | time.Sleep(2 * time.Second) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /basic/06memory/wrong_done/wrong_done.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/12/02 11:14:00 Change: 2019/12/02 11:47:44 2 | // FileName: wrong_done.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "sync" 11 | "time" 12 | ) 13 | 14 | var a string 15 | var done bool 16 | var once sync.Once 17 | 18 | func setup() { 19 | a = "hello, world" 20 | done = true 21 | } 22 | 23 | func doprint() { 24 | if !done { 25 | once.Do(setup) 26 | } 27 | println(a) 28 | } 29 | 30 | func twoprint() { 31 | go doprint() 32 | go doprint() 33 | } 34 | 35 | func main() { 36 | done = false 37 | a = "not hello, world" 38 | twoprint() 39 | time.Sleep(1 * time.Second) 40 | } 41 | -------------------------------------------------------------------------------- /basic/07marshal/unmarshal.go: -------------------------------------------------------------------------------- 1 | package unmarshal 2 | 3 | import "encoding/json" 4 | 5 | type Obj struct { 6 | Value int 7 | Array [100]int 8 | } 9 | 10 | type ObjP struct { 11 | Value int 12 | Array []int 13 | } 14 | 15 | func UnmarshalObj(str []byte, v interface{}) { 16 | json.Unmarshal(str, v) 17 | } 18 | 19 | func UnmarshalObjP(str []byte, v interface{}) { 20 | json.Unmarshal(str, v) 21 | } 22 | -------------------------------------------------------------------------------- /basic/07marshal/unmarshal_test.go: -------------------------------------------------------------------------------- 1 | package unmarshal 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var objstr_noarray = []byte(`{"Value":10}`) 8 | var objstr_array = []byte(`{"Value":10, "Array":[1,2,3,4,5,7,8]}`) 9 | 10 | func BenchmarkUnmarshalObjNoArray(b *testing.B) { 11 | for i := 0; i < b.N; i++ { 12 | obj := &Obj{} 13 | UnmarshalObj(objstr_noarray, obj) 14 | } 15 | } 16 | 17 | func BenchmarkUnmarshalObjPNoArray(b *testing.B) { 18 | for i := 0; i < b.N; i++ { 19 | obj := &ObjP{} 20 | UnmarshalObjP(objstr_noarray, obj) 21 | } 22 | } 23 | 24 | func BenchmarkUnmarshalObjArray(b *testing.B) { 25 | for i := 0; i < b.N; i++ { 26 | obj := &Obj{} 27 | UnmarshalObj(objstr_array, obj) 28 | } 29 | } 30 | 31 | func BenchmarkUnmarshalObjPArray(b *testing.B) { 32 | for i := 0; i < b.N; i++ { 33 | obj := &ObjP{} 34 | UnmarshalObjP(objstr_array, obj) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /basic/08goroutine/waitgroup/waitgroup.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | //问题1:主函数先于 go routine 退出 8 | //问题2:println(i) 打印的是 i 的当前值 9 | //问题3:wg 被复制 10 | func wg1() { 11 | wg := sync.WaitGroup{} 12 | 13 | for i := 0; i < 10; i++ { 14 | go func(wg sync.WaitGroup) { 15 | wg.Add(1) 16 | println(i) 17 | wg.Done() 18 | }(wg) 19 | } 20 | wg.Wait() 21 | } 22 | 23 | func wg2() { 24 | wg := sync.WaitGroup{} 25 | for i := 0; i < 10; i++ { 26 | go func(wg *sync.WaitGroup) { 27 | wg.Add(1) 28 | println(i) 29 | wg.Done() 30 | }(&wg) 31 | } 32 | wg.Wait() 33 | } 34 | 35 | func wg3() { 36 | wg := sync.WaitGroup{} 37 | 38 | for i := 0; i < 10; i++ { 39 | go func() { 40 | wg.Add(1) 41 | println(i) 42 | wg.Done() 43 | }() 44 | } 45 | wg.Wait() 46 | } 47 | 48 | func wg4() { 49 | wg := sync.WaitGroup{} 50 | 51 | for i := 0; i < 10; i++ { 52 | go func(i int) { 53 | wg.Add(1) 54 | println(i) 55 | wg.Done() 56 | }(i) 57 | } 58 | wg.Wait() 59 | } 60 | 61 | func wg5() { 62 | wg := sync.WaitGroup{} 63 | 64 | for i := 0; i < 10; i++ { 65 | wg.Add(1) 66 | go func(i int) { 67 | println(i) 68 | wg.Done() 69 | }(i) 70 | } 71 | wg.Wait() 72 | } 73 | 74 | func wg6() { 75 | wg := sync.WaitGroup{} 76 | 77 | for i := 0; i < 10; i++ { 78 | wg.Add(1) 79 | go func(i int, wg *sync.WaitGroup) { 80 | println(i) 81 | wg.Done() 82 | }(i, &wg) 83 | } 84 | wg.Wait() 85 | } 86 | 87 | func wg7() { 88 | wg := sync.WaitGroup{} 89 | 90 | for i := 0; i < 10; i++ { 91 | wg.Add(1) 92 | go func(i int, wg sync.WaitGroup) { 93 | println(i) 94 | wg.Done() 95 | }(i, wg) 96 | } 97 | wg.Wait() 98 | } 99 | 100 | func main() { 101 | //wg1() 102 | //wg2() 103 | //wg3() 104 | //wg4() 105 | //wg5() 106 | //wg6() 107 | wg7() 108 | } 109 | -------------------------------------------------------------------------------- /basic/09basicpkg/file/file.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/31 11:56:00 Change: 2019/07/31 11:57:03 2 | // FileName: file.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "os" 12 | 13 | "github.com/golang/glog" 14 | ) 15 | 16 | func main() { 17 | f, err := os.OpenFile("/tmp/go-open-file", os.O_CREATE|os.O_WRONLY, 0666) 18 | if err != nil { 19 | glog.Fatal(err.Error()) 20 | return 21 | } 22 | n, err := f.WriteString("hello") 23 | if err != nil { 24 | glog.Fatal(err) 25 | } else { 26 | fmt.Printf("Write %d\n", n) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /basic/09basicpkg/json/json.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 lijiaocn wechat: lijiaocn 2 | // 3 | // Distributed under terms of the GPL license. 4 | 5 | package main 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | 11 | "github.com/golang/glog" 12 | "time" 13 | ) 14 | 15 | type Node struct { 16 | Cluster string 17 | ID string 18 | Time time.Second 19 | } 20 | 21 | func main() { 22 | nodes := make([]Node, 0) 23 | nodes = append(nodes, 24 | Node{ 25 | Cluster: "cluster", 26 | ID: "1", 27 | Time: 5 * time.Second, 28 | }, 29 | Node{ 30 | Cluster: "cluster", 31 | ID: "2", 32 | }, 33 | Node{ 34 | Cluster: "cluster", 35 | ID: "3", 36 | }, 37 | ) 38 | 39 | str, err := json.Marshal(nodes) 40 | if err != nil { 41 | glog.Fatal(err) 42 | } 43 | fmt.Printf("%s\n", str) 44 | 45 | var nodes2 []Node 46 | if err := json.Unmarshal(str, &nodes2); err != nil { 47 | glog.Fatal(err) 48 | } else { 49 | for _, i := range nodes2 { 50 | fmt.Printf("%s %s\n", i.Cluster, i.ID) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /basic/09basicpkg/reflect/reflect.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/01 10:48:00 Change: 2019/07/01 14:52:31 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "reflect" 12 | ) 13 | 14 | type Struct1 struct{} 15 | 16 | func subfunc1(obj interface{}) { 17 | fmt.Println(reflect.TypeOf(obj).Name()) 18 | } 19 | 20 | func main() { 21 | s1 := Struct1{} 22 | fmt.Println(reflect.TypeOf(s1).Name()) 23 | subfunc1(s1) 24 | fmt.Println("abc:", reflect.TypeOf(subfunc1).Name()) 25 | } 26 | -------------------------------------------------------------------------------- /basic/09basicpkg/signal/signal.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 lijiaocn wechat: lijiaocn 2 | // 3 | // Distributed under terms of the GPL license. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "os/signal" 11 | "syscall" 12 | ) 13 | 14 | func sigusr1() { 15 | fmt.Printf("Recevie SIGUSR1") 16 | } 17 | 18 | func main() { 19 | 20 | //Set signal 21 | signalChan := make(chan os.Signal) 22 | signal.Notify(signalChan, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGUSR1) 23 | for { 24 | select { 25 | case s := <-signalChan: 26 | switch s { 27 | case syscall.SIGQUIT: 28 | fallthrough 29 | case syscall.SIGKILL: 30 | fallthrough 31 | case syscall.SIGTERM: 32 | os.Exit(1) 33 | case syscall.SIGUSR1: 34 | sigusr1() 35 | default: 36 | continue 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /basic/09basicpkg/syncmap/syncmap.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 lijiaocn wechat: lijiaocn 2 | // 3 | // Distributed under terms of the GPL license. 4 | 5 | package main 6 | 7 | import ( 8 | "math/rand" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | type Var struct { 14 | Value int 15 | } 16 | 17 | const NUM = 100 18 | 19 | func insert(m *sync.Map) { 20 | for i := 1; i < NUM; i++ { 21 | key := i 22 | v := Var{Value: i} 23 | println("insert key: ", key) 24 | m.Store(i, v) 25 | } 26 | } 27 | 28 | func read(m *sync.Map) { 29 | for i := 1; i < NUM; i++ { 30 | key := i 31 | if v, ok := m.Load(i); ok { 32 | if value, ok := v.(Var); ok { 33 | println("read key: ", key, " value is: ", value.Value) 34 | } else { 35 | println("value's type is wrong") 36 | } 37 | } else { 38 | println("not found value for key: ", key) 39 | } 40 | } 41 | } 42 | 43 | func delete(m *sync.Map) { 44 | for i := 1; i < NUM/3; i++ { 45 | random := rand.Int() 46 | key := random % NUM 47 | println("delete key: ", key) 48 | m.Delete(key) 49 | } 50 | } 51 | 52 | func printFunc(key, value interface{}) bool { 53 | k, ok := key.(int) 54 | if !ok { 55 | println("key's type is wrong") 56 | } 57 | v, ok := value.(Var) 58 | if !ok { 59 | println("value's type is wrong") 60 | } 61 | println("range key is ", k, " value is ", v.Value) 62 | return true 63 | } 64 | 65 | func isEmpty(m *sync.Map) bool { 66 | isEmpty := true 67 | m.Range(func(key, value interface{}) bool { 68 | isEmpty = false 69 | return false 70 | }) 71 | return isEmpty 72 | } 73 | 74 | func main() { 75 | // m1 := &sync.Map{} 76 | // 77 | // go insert(m1) 78 | // // go delete(m1) 79 | // go read(m1) 80 | // 81 | // time.Sleep(5 * time.Second) 82 | // m1.Range(printFunc) 83 | 84 | m2 := &sync.Map{} 85 | if isEmpty(m2) { 86 | println("1: is empty") 87 | } else { 88 | println("1: not empty") 89 | } 90 | 91 | m2.Store(1, 1) 92 | if isEmpty(m2) { 93 | println("2: is empty") 94 | } else { 95 | println("2: not empty") 96 | } 97 | 98 | m2.Delete(1) 99 | if isEmpty(m2) { 100 | println("2: is empty") 101 | } else { 102 | println("2: not empty") 103 | } 104 | time.Sleep(5 * time.Second) 105 | } 106 | -------------------------------------------------------------------------------- /basic/09basicpkg/timeticker/timeticker.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/01 14:14:00 Change: 2019/07/01 14:30:22 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "time" 11 | ) 12 | 13 | func main() { 14 | ticker := time.NewTicker(1 * time.Second) 15 | for { 16 | select { 17 | case <-ticker.C: 18 | println("1") 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /basic/10gomod/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "lijiaocn.com/go/example/mod" 4 | import "lijiaocn.com/go/example/mod/v2" 5 | //import "lijiaocn.com/go/example/mod/v3" 6 | 7 | func main() { 8 | mod.Version() 9 | v2.Version() 10 | // v3.Version() 11 | } -------------------------------------------------------------------------------- /basic/11debug/debug.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func Write(num int, c chan int) { 9 | for { 10 | c <- num 11 | } 12 | } 13 | 14 | func main() { 15 | c := make(chan int) 16 | go Write(10, c) 17 | go Write(20, c) 18 | for { 19 | select { 20 | case v := <-c: 21 | fmt.Printf("receive %d\n", v) 22 | time.Sleep(2 * time.Second) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /basic/12convert/convert.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "encoding/json" 7 | "fmt" 8 | "log" 9 | "math" 10 | "time" 11 | 12 | yaml "gopkg.in/yaml.v2" 13 | ) 14 | 15 | type Attr struct { 16 | Value string `yaml:"value"` 17 | } 18 | 19 | type Student struct { 20 | Name string `yaml:"name"` 21 | Attrs map[int]Attr `yaml:"attrs"` 22 | } 23 | 24 | func Base64Convert() { 25 | fmt.Println("###### Base64Convert #####") 26 | msg := "Hello, 世界" 27 | encoded := base64.StdEncoding.EncodeToString([]byte(msg)) 28 | fmt.Println("base64: %s", encoded) 29 | decoded, err := base64.StdEncoding.DecodeString(encoded) 30 | if err != nil { 31 | fmt.Println("decode error:", err) 32 | return 33 | } 34 | fmt.Println(string(decoded)) 35 | } 36 | 37 | func UintAndInt() { 38 | var uint_a uint64 = 100000 39 | fmt.Printf("uint: %d to int: %d\n", uint_a, int64(uint_a)) 40 | } 41 | 42 | func Floor() { 43 | var a int32 = 80 44 | var b int32 = 100 45 | c := int32(math.Floor(float64(b) * (float64(a) / 100))) 46 | fmt.Println("%d", c) 47 | 48 | a = -3 49 | fmt.Println("absoulte is: ", math.Abs(float64(a))) 50 | fmt.Printf("current time is: %s\n", time.Now().Format("2020-02-20T03:03:07Z")) 51 | } 52 | 53 | func Yaml() { 54 | s := Student{ 55 | Name: "lijiaocn", 56 | Attrs: map[int]Attr{ 57 | 0: {Value: "hello1"}, 58 | 1: {Value: "hello2"}, 59 | }, 60 | } 61 | 62 | if out, err := yaml.Marshal(s); err != nil { 63 | log.Fatal(err) 64 | } else { 65 | fmt.Printf("%s\n", out) 66 | } 67 | 68 | } 69 | func Json() { 70 | s := Student{ 71 | Name: "lijiaocn", 72 | Attrs: map[int]Attr{ 73 | 0: {Value: "hello1"}, 74 | 1: {Value: "hello2"}, 75 | }, 76 | } 77 | 78 | studentss := make([]Student, 10, 10) 79 | studentss = append(studentss, s, s, s, s) 80 | content, _ := json.Marshal(studentss) 81 | fmt.Printf("%s\n", string(content)) 82 | 83 | ints := "[1,2,3]" 84 | intlist := make([]int, 0) 85 | if err := json.Unmarshal([]byte(ints), &intlist); err != nil { 86 | log.Panic(err) 87 | } 88 | fmt.Println(intlist) 89 | } 90 | 91 | func Json2() { 92 | s := Student{ 93 | Name: "lijiaocn", 94 | Attrs: map[int]Attr{ 95 | 0: {Value: "hello1"}, 96 | 1: {Value: "hello2"}, 97 | }, 98 | } 99 | var buf bytes.Buffer 100 | if err := json.NewEncoder(&buf).Encode(s); err != nil { 101 | log.Panic(err.Error()) 102 | } 103 | fmt.Printf("%s", buf.String()) 104 | } 105 | 106 | func main() { 107 | Base64Convert() 108 | UintAndInt() 109 | Json() 110 | Json2() 111 | } 112 | -------------------------------------------------------------------------------- /basic/13httpserver/01default/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | func defaultServer(addr string) { 10 | http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) { 11 | writer.Write([]byte("Hello World!")) 12 | }) 13 | log.Fatal(http.ListenAndServe(":8081", nil)) 14 | } 15 | 16 | func main() { 17 | // $ curl 127.0.0.1:8081/hello 18 | // Hello World!% 19 | go defaultServer(":8081") 20 | time.Sleep(1000 * time.Second) 21 | } 22 | -------------------------------------------------------------------------------- /basic/13httpserver/02defserver/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | type NewHandler struct{} 10 | 11 | func (s *NewHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) { 12 | // 根据 req 查找对应的 handler 13 | if req.URL.Path == "/hello2" { 14 | writer.Write([]byte("Hello2 World!")) 15 | } 16 | } 17 | 18 | func defServer(addr string) { 19 | s := &http.Server{ 20 | Addr: addr, 21 | Handler: nil, 22 | TLSConfig: nil, 23 | ReadTimeout: 0, 24 | ReadHeaderTimeout: 0, 25 | WriteTimeout: 0, 26 | IdleTimeout: 0, 27 | MaxHeaderBytes: 0, 28 | TLSNextProto: nil, 29 | ConnState: nil, 30 | ErrorLog: nil, 31 | BaseContext: nil, 32 | ConnContext: nil, 33 | } 34 | s.Handler = &NewHandler{} 35 | log.Fatal(s.ListenAndServe()) 36 | } 37 | 38 | func main() { 39 | // $ curl 127.0.0.1:8082/hello2 40 | // Hello2 World!% 41 | go defServer(":8082") 42 | time.Sleep(1000 * time.Second) 43 | } 44 | -------------------------------------------------------------------------------- /basic/13httpserver/03mux/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | func defServer(addr string) { 10 | s := &http.Server{ 11 | Addr: addr, 12 | Handler: nil, 13 | TLSConfig: nil, 14 | ReadTimeout: 0, 15 | ReadHeaderTimeout: 0, 16 | WriteTimeout: 0, 17 | IdleTimeout: 0, 18 | MaxHeaderBytes: 0, 19 | TLSNextProto: nil, 20 | ConnState: nil, 21 | ErrorLog: nil, 22 | BaseContext: nil, 23 | ConnContext: nil, 24 | } 25 | s.Handler = serveMux() 26 | log.Fatal(s.ListenAndServe()) 27 | } 28 | 29 | func serveMux() *http.ServeMux { 30 | mux := http.NewServeMux() 31 | mux.HandleFunc("/hello3", func(writer http.ResponseWriter, request *http.Request) { 32 | writer.Write([]byte("Hello3 World!")) 33 | }) 34 | return mux 35 | } 36 | 37 | func main() { 38 | // $ curl 127.0.0.1:8083/hello3 39 | // Hello3 World! 40 | go defServer(":8083") 41 | time.Sleep(1000 * time.Second) 42 | } 43 | -------------------------------------------------------------------------------- /basic/13httpserver/httpserver.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | func defaultServer(addr string) { 10 | http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) { 11 | writer.Write([]byte("Hello World!")) 12 | }) 13 | log.Fatal(http.ListenAndServe(":8081", nil)) 14 | } 15 | 16 | type NewHandler struct{} 17 | 18 | func (s *NewHandler) ServeHTTP(writer http.ResponseWriter, req *http.Request) { 19 | // 根据 req 查找对应的 handler 20 | if req.URL.Path == "/hello2" { 21 | writer.Write([]byte("Hello2 World!")) 22 | } 23 | } 24 | 25 | func defServer(addr string) { 26 | s := &http.Server{ 27 | Addr: addr, 28 | Handler: nil, 29 | TLSConfig: nil, 30 | ReadTimeout: 0, 31 | ReadHeaderTimeout: 0, 32 | WriteTimeout: 0, 33 | IdleTimeout: 0, 34 | MaxHeaderBytes: 0, 35 | TLSNextProto: nil, 36 | ConnState: nil, 37 | ErrorLog: nil, 38 | BaseContext: nil, 39 | ConnContext: nil, 40 | } 41 | s.Handler = &NewHandler{} 42 | log.Fatal(s.ListenAndServe()) 43 | } 44 | 45 | func serveMux() { 46 | mux := http.NewServeMux() 47 | mux.HandleFunc("/hello3", func(writer http.ResponseWriter, request *http.Request) { 48 | writer.Write([]byte("Hello3 World!")) 49 | }) 50 | 51 | } 52 | 53 | func main() { 54 | // $ curl 127.0.0.1:8081/hello 55 | // Hello World!% 56 | go defaultServer(":8081") 57 | // $ curl 127.0.0.1:8082/hello2 58 | // Hello2 World!% 59 | go defServer(":8082") 60 | 61 | go serveMux() 62 | 63 | time.Sleep(1000 * time.Second) 64 | } 65 | -------------------------------------------------------------------------------- /basic/14pmisc/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Printf("%d\n", len(make([]int, 0))) 7 | } 8 | -------------------------------------------------------------------------------- /basic/16const/iota.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const ( 6 | ErrorCodeConfig = 60000300 + iota 7 | ErrorCodeConfigList 8 | ErrorCodeConfigList2 9 | ) 10 | 11 | const ( 12 | a = 100 * iota //0 13 | b = 100 * iota 14 | c = 100 * iota 15 | ) 16 | 17 | const ( 18 | A = c + iota 19 | B 20 | C 21 | ) 22 | 23 | func main() { 24 | fmt.Println(ErrorCodeConfigList) 25 | fmt.Println(ErrorCodeConfigList2) 26 | fmt.Printf("c is: %d\n", c) 27 | fmt.Printf("C is: %d\n", C) 28 | } 29 | -------------------------------------------------------------------------------- /basic/17time/time.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func UnixSecond() { 9 | fmt.Printf("Unix Seconds: %d\n", time.Now().Unix()) 10 | } 11 | 12 | func main() { 13 | UnixSecond() 14 | } 15 | -------------------------------------------------------------------------------- /basic/18arith/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | //func illegeDiv() { 6 | // fmt.Printf("%d", 1/0) 7 | //} 8 | func illegeFloatDiv(a, b float64) { 9 | fmt.Println("%d", a/b) 10 | } 11 | 12 | func float64Euqal(a, b float64) { 13 | if a == b { 14 | fmt.Println("float64Euqal") 15 | } 16 | } 17 | 18 | func main() { 19 | //illegeDiv() 20 | illegeFloatDiv(0, 0) 21 | float64Euqal(0, 0) 22 | } 23 | -------------------------------------------------------------------------------- /basic/19slice/slice.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | s := make([]int, 0, 5) 7 | s = append(s, 5) 8 | s = append(s, 10) 9 | s = append(s, 11) 10 | fmt.Println(s) 11 | s2 := make([]int, 2, 5) 12 | s2 = append(s2, 5) 13 | s2 = append(s2, 10) 14 | s2 = append(s2, 11) 15 | fmt.Println(s2) 16 | } 17 | -------------------------------------------------------------------------------- /cadvisor/.gitignore: -------------------------------------------------------------------------------- 1 | cadvisor 2 | -------------------------------------------------------------------------------- /cadvisor/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "time" 7 | 8 | "github.com/google/cadvisor/client" 9 | v1 "github.com/google/cadvisor/info/v1" 10 | "github.com/sirupsen/logrus" 11 | ) 12 | 13 | func GroupByPod(cinfo []v1.ContainerInfo) (map[string][]v1.ContainerInfo, error) { 14 | groups := make(map[string][]v1.ContainerInfo) 15 | for _, v := range cinfo { 16 | key := strings.Split(v.Name, v.Id)[0] 17 | _, ok := groups[key] 18 | if !ok { 19 | groups[key] = make([]v1.ContainerInfo, 1) 20 | groups[key][0] = v 21 | continue 22 | } 23 | groups[key] = append(groups[key], v) 24 | } 25 | return groups, nil 26 | } 27 | 28 | func main() { 29 | cadvisor, err := client.NewClient("http://172.29.128.20:8080") 30 | cinfoList, err := cadvisor.AllDockerContainers( 31 | &v1.ContainerInfoRequest{ 32 | NumStats: 60, 33 | Start: time.Time{}, 34 | End: time.Time{}, 35 | }) 36 | if err != nil { 37 | logrus.Errorf("read cadvisor fail, stop collect: %s", err.Error()) 38 | return 39 | } 40 | 41 | //bytes, err := json.MarshalIndent(cinfoList, "", " ") 42 | //if err != nil { 43 | // glog.Fatal(err.Error()) 44 | //} 45 | //fmt.Printf("%s\n", bytes) 46 | 47 | pods, _ := GroupByPod(cinfoList) 48 | for key, v := range pods { 49 | fmt.Printf("%s: %s\n", key, v[0].Aliases[0]) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /envoydev/README.md: -------------------------------------------------------------------------------- 1 | # envoy 开发 2 | 3 | go mod init github.com/introclass/go-code-example/envoydev 4 | go get github.com/envoyproxy/go-control-plane@v0.8.3 5 | 6 | ## 7 | 8 | ▸ xds/ 9 | -------------------------------------------------------------------------------- /envoydev/xds/.gitignore: -------------------------------------------------------------------------------- 1 | xds 2 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/envoy-0-default.yaml: -------------------------------------------------------------------------------- 1 | admin: 2 | access_log_path: /tmp/admin_access.log 3 | address: 4 | socket_address: 5 | protocol: TCP 6 | address: 127.0.0.1 7 | port_value: 9901 8 | static_resources: 9 | listeners: 10 | - name: listener_0 11 | address: 12 | socket_address: 13 | protocol: TCP 14 | address: 0.0.0.0 15 | port_value: 10000 16 | filter_chains: 17 | - filters: 18 | - name: envoy.http_connection_manager 19 | typed_config: 20 | "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager 21 | stat_prefix: ingress_http 22 | route_config: 23 | name: local_route 24 | virtual_hosts: 25 | - name: local_service 26 | domains: ["*"] 27 | routes: 28 | - match: 29 | prefix: "/" 30 | route: 31 | host_rewrite: www.google.com 32 | cluster: service_google 33 | http_filters: 34 | - name: envoy.router 35 | clusters: 36 | - name: service_google 37 | connect_timeout: 0.25s 38 | type: LOGICAL_DNS 39 | # Comment out the following line to test on v6 networks 40 | dns_lookup_family: V4_ONLY 41 | lb_policy: ROUND_ROBIN 42 | load_assignment: 43 | cluster_name: service_google 44 | endpoints: 45 | - lb_endpoints: 46 | - endpoint: 47 | address: 48 | socket_address: 49 | address: www.google.com 50 | port_value: 443 51 | tls_context: 52 | sni: www.google.com 53 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/envoy-0-example.yaml: -------------------------------------------------------------------------------- 1 | node: 2 | id: "envoy-64.58" 3 | cluster: "test" 4 | #runtime: 5 | # symlink_root: /srv/runtime/current 6 | # subdirectory: envoy 7 | # override_subdirectory: envoy_override 8 | watchdog: 9 | miss_timeout: 0.2s 10 | megamiss_timeout: 1s 11 | kill_timeout: 0s 12 | multikill_timeout: 0s 13 | flags_path: /etc/envoy/flags/ 14 | stats_flush_interval: 5s 15 | stats_config: 16 | use_all_default_tags: true 17 | stats_sinks: 18 | name: envoy.stat_sinks.hystrix 19 | config: 20 | num_buckets: 10 21 | admin: 22 | access_log_path: /var/log/envoy/admin_access.log 23 | profile_path: /var/log/envoy/envoy.prof 24 | address: 25 | socket_address: 26 | protocol: TCP 27 | address: 0.0.0.0 28 | port_value: 9901 29 | static_resources: 30 | listeners: 31 | - name: listener_0 32 | address: 33 | socket_address: 34 | protocol: TCP 35 | address: 0.0.0.0 36 | port_value: 80 37 | filter_chains: 38 | - filters: 39 | - name: envoy.http_connection_manager 40 | typed_config: 41 | "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager 42 | stat_prefix: ingress_http 43 | route_config: 44 | name: local_route 45 | virtual_hosts: 46 | - name: local_service 47 | domains: ["*"] 48 | routes: 49 | - match: 50 | prefix: "/" 51 | route: 52 | host_rewrite: www.baidu.com 53 | cluster: service_echo 54 | http_filters: 55 | - name: envoy.router 56 | clusters: 57 | - name: ads_cluster 58 | connect_timeout: 0.25s 59 | type: STATIC 60 | lb_policy: ROUND_ROBIN 61 | http2_protocol_options: {} 62 | load_assignment: 63 | cluster_name: ads_cluster 64 | endpoints: 65 | - lb_endpoints: 66 | - endpoint: 67 | address: 68 | socket_address: 69 | address: 127.0.0.1 70 | port_value: 5678 71 | - name: xds_cluster 72 | connect_timeout: 0.25s 73 | type: STATIC 74 | lb_policy: ROUND_ROBIN 75 | http2_protocol_options: {} 76 | load_assignment: 77 | cluster_name: xds_cluster 78 | endpoints: 79 | - lb_endpoints: 80 | - endpoint: 81 | address: 82 | socket_address: 83 | address: 127.0.0.1 84 | port_value: 5678 85 | - name: service_echo 86 | connect_timeout: 0.25s 87 | type: STATIC 88 | lb_policy: ROUND_ROBIN 89 | #http2_protocol_options: {} 90 | load_assignment: 91 | cluster_name: service_echo 92 | endpoints: 93 | - lb_endpoints: 94 | - endpoint: 95 | address: 96 | socket_address: 97 | address: 172.17.0.2 98 | port_value: 8080 99 | - name: service_baidu 100 | connect_timeout: 0.25s 101 | type: LOGICAL_DNS 102 | # Comment out the following line to test on v6 networks 103 | dns_lookup_family: V4_ONLY 104 | lb_policy: ROUND_ROBIN 105 | load_assignment: 106 | cluster_name: service_baidu 107 | endpoints: 108 | - lb_endpoints: 109 | - endpoint: 110 | address: 111 | socket_address: 112 | address: www.baidu.com 113 | port_value: 443 114 | tls_context: 115 | sni: www.baidu.com 116 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/envoy-1-ads-with-xds.yaml: -------------------------------------------------------------------------------- 1 | node: 2 | id: "envoy-64.58" 3 | cluster: "test" 4 | #runtime: 5 | # symlink_root: /srv/runtime/current 6 | # subdirectory: envoy 7 | # override_subdirectory: envoy_override 8 | watchdog: 9 | miss_timeout: 0.2s 10 | megamiss_timeout: 1s 11 | kill_timeout: 0s 12 | multikill_timeout: 0s 13 | flags_path: /etc/envoy/flags/ 14 | stats_flush_interval: 5s 15 | stats_config: 16 | use_all_default_tags: true 17 | stats_sinks: 18 | name: envoy.stat_sinks.hystrix 19 | config: 20 | num_buckets: 10 21 | admin: 22 | access_log_path: /var/log/envoy/admin_access.log 23 | profile_path: /var/log/envoy/envoy.prof 24 | address: 25 | socket_address: 26 | protocol: TCP 27 | address: 0.0.0.0 28 | port_value: 9901 29 | dynamic_resources: 30 | ads_config: 31 | api_type: GRPC 32 | grpc_services: 33 | envoy_grpc: 34 | cluster_name: ads_cluster 35 | cds_config: {ads: {}} 36 | lds_config: {ads: {}} 37 | static_resources: 38 | clusters: 39 | - name: ads_cluster 40 | connect_timeout: 0.25s 41 | type: STATIC 42 | lb_policy: ROUND_ROBIN 43 | http2_protocol_options: {} 44 | load_assignment: 45 | cluster_name: ads_cluster 46 | endpoints: 47 | - lb_endpoints: 48 | - endpoint: 49 | address: 50 | socket_address: 51 | #address: 127.0.0.1 52 | address: 192.168.99.1 53 | port_value: 5678 54 | - name: xds_cluster 55 | connect_timeout: 0.25s 56 | type: STATIC 57 | lb_policy: ROUND_ROBIN 58 | http2_protocol_options: {} 59 | load_assignment: 60 | cluster_name: xds_cluster 61 | endpoints: 62 | - lb_endpoints: 63 | - endpoint: 64 | address: 65 | socket_address: 66 | #address: 127.0.0.1 67 | address: 192.168.99.1 68 | port_value: 5678 69 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/envoy-1-ads.yaml: -------------------------------------------------------------------------------- 1 | node: 2 | id: "envoy-64.58" 3 | cluster: "test" 4 | #runtime: 5 | # symlink_root: /srv/runtime/current 6 | # subdirectory: envoy 7 | # override_subdirectory: envoy_override 8 | watchdog: 9 | miss_timeout: 0.2s 10 | megamiss_timeout: 1s 11 | kill_timeout: 0s 12 | multikill_timeout: 0s 13 | flags_path: /etc/envoy/flags/ 14 | stats_flush_interval: 5s 15 | stats_config: 16 | use_all_default_tags: true 17 | stats_sinks: 18 | name: envoy.stat_sinks.hystrix 19 | config: 20 | num_buckets: 10 21 | admin: 22 | access_log_path: /var/log/envoy/admin_access.log 23 | profile_path: /var/log/envoy/envoy.prof 24 | address: 25 | socket_address: 26 | protocol: TCP 27 | address: 0.0.0.0 28 | port_value: 9901 29 | dynamic_resources: 30 | ads_config: 31 | api_type: GRPC 32 | grpc_services: 33 | envoy_grpc: 34 | cluster_name: ads_cluster 35 | cds_config: {ads: {}} 36 | lds_config: {ads: {}} 37 | static_resources: 38 | clusters: 39 | - name: ads_cluster 40 | connect_timeout: 0.25s 41 | type: STATIC 42 | lb_policy: ROUND_ROBIN 43 | http2_protocol_options: {} 44 | load_assignment: 45 | cluster_name: ads_cluster 46 | endpoints: 47 | - lb_endpoints: 48 | - endpoint: 49 | address: 50 | socket_address: 51 | #address: 127.0.0.1 52 | address: 192.168.99.1 53 | port_value: 5678 54 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/envoy-1-static.yaml: -------------------------------------------------------------------------------- 1 | node: 2 | id: "envoy-64.58" 3 | cluster: "test" 4 | #runtime: 5 | # symlink_root: /srv/runtime/current 6 | # subdirectory: envoy 7 | # override_subdirectory: envoy_override 8 | #flags_path: /etc/envoy/flags/ 9 | watchdog: 10 | miss_timeout: 0.2s 11 | megamiss_timeout: 1s 12 | kill_timeout: 0s 13 | multikill_timeout: 0s 14 | stats_flush_interval: 5s 15 | stats_config: 16 | use_all_default_tags: true 17 | stats_sinks: 18 | name: envoy.stat_sinks.hystrix 19 | config: 20 | num_buckets: 10 21 | admin: 22 | access_log_path: /var/log/envoy/admin_access.log 23 | profile_path: /var/log/envoy/envoy.prof 24 | address: 25 | socket_address: 26 | protocol: TCP 27 | address: 0.0.0.0 28 | port_value: 9901 29 | static_resources: 30 | listeners: 31 | - name: listener_0 32 | address: 33 | socket_address: 34 | protocol: TCP 35 | address: 0.0.0.0 36 | port_value: 80 37 | filter_chains: 38 | - filters: 39 | - name: envoy.http_connection_manager 40 | config: 41 | stat_prefix: ingress_http 42 | generate_request_id: true 43 | route_config: 44 | name: local_route 45 | virtual_hosts: 46 | - name: local_service 47 | domains: ["echo.com"] 48 | routes: 49 | - match: 50 | prefix: "/" 51 | route: 52 | host_rewrite: echo.com 53 | cluster: service_echo 54 | http_filters: 55 | - name: envoy.router 56 | config: 57 | dynamic_stats: false 58 | - name: listener_1 59 | address: 60 | socket_address: 61 | protocol: TCP 62 | address: 0.0.0.0 63 | port_value: 81 64 | filter_chains: 65 | - filters: 66 | - name: envoy.http_connection_manager 67 | typed_config: 68 | "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager 69 | stat_prefix: ingress_http 70 | route_config: 71 | name: local_route 72 | virtual_hosts: 73 | - name: local_service 74 | domains: ["*"] 75 | routes: 76 | - match: 77 | prefix: "/" 78 | route: 79 | host_rewrite: www.baidu.com 80 | cluster: service_baidu 81 | http_filters: 82 | - name: envoy.router 83 | clusters: 84 | - name: service_echo 85 | connect_timeout: 0.25s 86 | type: static 87 | lb_policy: ROUND_ROBIN 88 | hosts: 89 | - socket_address: 90 | address: 172.17.0.2 91 | port_value: 8080 92 | # - name: service_echo 93 | # connect_timeout: 0.25s 94 | # type: STATIC 95 | # lb_policy: ROUND_ROBIN 96 | # #http2_protocol_options: {} #echoserver不支持http 2.0 97 | # load_assignment: 98 | # cluster_name: service_echo 99 | # endpoints: 100 | # - lb_endpoints: 101 | # - endpoint: 102 | # address: 103 | # socket_address: 104 | # address: 172.17.0.2 105 | # port_value: 8080 106 | - name: service_baidu 107 | connect_timeout: 0.25s 108 | type: LOGICAL_DNS 109 | dns_lookup_family: V4_ONLY 110 | lb_policy: ROUND_ROBIN 111 | load_assignment: 112 | cluster_name: service_baidu 113 | endpoints: 114 | - lb_endpoints: 115 | - endpoint: 116 | address: 117 | socket_address: 118 | address: www.baidu.com 119 | port_value: 443 120 | tls_context: 121 | sni: www.baidu.com 122 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/envoy-1-xds.yaml: -------------------------------------------------------------------------------- 1 | node: 2 | id: "envoy-64.58" 3 | cluster: "test" 4 | #runtime: 5 | # symlink_root: /srv/runtime/current 6 | # subdirectory: envoy 7 | # override_subdirectory: envoy_override 8 | watchdog: 9 | miss_timeout: 0.2s 10 | megamiss_timeout: 1s 11 | kill_timeout: 0s 12 | multikill_timeout: 0s 13 | flags_path: /etc/envoy/flags/ 14 | stats_flush_interval: 5s 15 | stats_config: 16 | use_all_default_tags: true 17 | stats_sinks: 18 | name: envoy.stat_sinks.hystrix 19 | config: 20 | num_buckets: 10 21 | admin: 22 | access_log_path: /var/log/envoy/admin_access.log 23 | profile_path: /var/log/envoy/envoy.prof 24 | address: 25 | socket_address: 26 | protocol: TCP 27 | address: 0.0.0.0 28 | port_value: 9901 29 | dynamic_resources: 30 | cds_config: 31 | api_config_source: 32 | api_type: GRPC 33 | grpc_services: 34 | envoy_grpc: 35 | cluster_name: xds_cluster 36 | lds_config: 37 | api_config_source: 38 | api_type: GRPC 39 | grpc_services: 40 | envoy_grpc: 41 | cluster_name: xds_cluster 42 | static_resources: 43 | clusters: 44 | - name: xds_cluster 45 | connect_timeout: 0.25s 46 | type: STATIC 47 | lb_policy: ROUND_ROBIN 48 | http2_protocol_options: {} 49 | load_assignment: 50 | cluster_name: xds_cluster 51 | endpoints: 52 | - lb_endpoints: 53 | - endpoint: 54 | address: 55 | socket_address: 56 | #address: 127.0.0.1 57 | address: 192.168.99.1 58 | port_value: 5678 59 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/envoy-to-grpc-svc.yaml: -------------------------------------------------------------------------------- 1 | node: 2 | id: "envoy-64.58" 3 | cluster: "test" 4 | runtime: 5 | symlink_root: /srv/runtime/current 6 | subdirectory: envoy 7 | override_subdirectory: envoy_override 8 | watchdog: 9 | miss_timeout: 0.2s 10 | megamiss_timeout: 1s 11 | kill_timeout: 0s 12 | multikill_timeout: 0s 13 | flags_path: /etc/envoy/flags/ 14 | stats_flush_interval: 5s 15 | stats_config: 16 | use_all_default_tags: true 17 | stats_sinks: 18 | name: envoy.stat_sinks.hystrix 19 | config: 20 | num_buckets: 10 21 | admin: 22 | access_log_path: /tmp/admin_access.log 23 | profile_path: /var/log/envoy/envoy.prof 24 | address: 25 | socket_address: 26 | protocol: TCP 27 | address: 0.0.0.0 28 | port_value: 9901 29 | static_resources: 30 | listeners: 31 | - name: listener_0 32 | address: 33 | socket_address: 34 | protocol: TCP 35 | address: 0.0.0.0 36 | port_value: 50050 37 | filter_chains: 38 | - filters: 39 | - name: envoy.http_connection_manager 40 | config: 41 | stat_prefix: ingress_http 42 | generate_request_id: true 43 | route_config: 44 | name: local_route 45 | virtual_hosts: 46 | - name: local_service 47 | domains: ["*"] 48 | routes: 49 | - match: 50 | prefix: "/" 51 | grpc: {} 52 | route: 53 | cluster: service_grpc 54 | http_filters: 55 | - name: envoy.router 56 | config: 57 | dynamic_stats: false 58 | clusters: 59 | - name: service_grpc 60 | connect_timeout: 0.25s 61 | type: static 62 | # lb_policy: ROUND_ROBIN 63 | lb_policy: LEAST_REQUEST 64 | # lb_policy: RANDOM 65 | http2_protocol_options: {} # enable http2 protocol 66 | hosts: 67 | - socket_address: 68 | address: 10.10.64.58 69 | port_value: 50051 70 | - socket_address: 71 | address: 10.10.64.58 72 | port_value: 50052 73 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/envoy-to-tcp.yaml: -------------------------------------------------------------------------------- 1 | node: 2 | id: "envoy-64.58" 3 | cluster: "test" 4 | #runtime: 5 | # symlink_root: /srv/runtime/current 6 | # subdirectory: envoy 7 | # override_subdirectory: envoy_override 8 | #flags_path: /etc/envoy/flags/ 9 | watchdog: 10 | miss_timeout: 0.2s 11 | megamiss_timeout: 1s 12 | kill_timeout: 0s 13 | multikill_timeout: 0s 14 | stats_flush_interval: 5s 15 | stats_config: 16 | use_all_default_tags: true 17 | stats_sinks: 18 | name: envoy.stat_sinks.hystrix 19 | config: 20 | num_buckets: 10 21 | admin: 22 | access_log_path: /var/log/envoy/admin_access.log 23 | profile_path: /var/log/envoy/envoy.prof 24 | address: 25 | socket_address: 26 | protocol: TCP 27 | address: 0.0.0.0 28 | port_value: 9901 29 | static_resources: 30 | listeners: 31 | - name: listener_0 32 | address: 33 | socket_address: 34 | protocol: TCP 35 | address: 0.0.0.0 36 | port_value: 81 37 | filter_chains: 38 | - filters: 39 | - name: envoy.tcp_proxy 40 | config: 41 | stat_prefix: tcp_proxy_81 42 | cluster: echo_tcp_80 43 | - name: listener_1 44 | address: 45 | socket_address: 46 | protocol: TCP 47 | address: 0.0.0.0 48 | port_value: 81 49 | filter_chains: 50 | - filters: 51 | - name: envoy.tcp_proxy 52 | config: 53 | stat_prefix: tcp_proxy_81 54 | cluster: echo_tcp_80 55 | clusters: 56 | - name: echo_tcp_80 57 | connect_timeout: 0.25s 58 | type: STATIC 59 | lb_policy: ROUND_ROBIN 60 | #http2_protocol_options: {} #echoserver不支持http 2.0 61 | load_assignment: 62 | cluster_name: service_echo 63 | endpoints: 64 | - lb_endpoints: 65 | - endpoint: 66 | address: 67 | socket_address: 68 | address: 172.17.0.2 69 | port_value: 8080 70 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/log/admin_access.log: -------------------------------------------------------------------------------- 1 | [2019-08-09T18:28:02.568Z] "GET / HTTP/1.0" 426 - 0 0 0 - "-" "-" "-" "-" "-" 2 | [2019-08-09T18:28:07.574Z] "OPTIONS / HTTP/1.0" 426 - 0 0 0 - "-" "-" "-" "-" "-" 3 | [2019-08-09T18:28:12.582Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 4 | [2019-08-09T18:28:12.626Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 5 | [2019-08-09T18:28:12.689Z] "GET /nice%20ports%2C/Tri%6Eity.txt%2ebak HTTP/1.0" 426 - 0 0 0 - "-" "-" "-" "-" "-" 6 | [2019-08-09T18:28:17.726Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 7 | [2019-08-09T18:28:17.737Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 8 | [2019-08-09T18:28:17.756Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 9 | [2019-08-09T18:28:17.826Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 10 | [2019-08-10T18:27:24.065Z] "GET / HTTP/1.0" 426 - 0 0 0 - "-" "-" "-" "-" "-" 11 | [2019-08-10T18:27:29.072Z] "OPTIONS / HTTP/1.0" 426 - 0 0 0 - "-" "-" "-" "-" "-" 12 | [2019-08-10T18:27:34.080Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 13 | [2019-08-10T18:27:34.124Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 14 | [2019-08-10T18:27:34.187Z] "GET /nice%20ports%2C/Tri%6Eity.txt%2ebak HTTP/1.0" 426 - 0 0 0 - "-" "-" "-" "-" "-" 15 | [2019-08-10T18:27:39.223Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 16 | [2019-08-10T18:27:39.234Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 17 | [2019-08-10T18:27:39.254Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 18 | [2019-08-10T18:27:39.322Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 19 | [2019-08-11T18:27:50.113Z] "GET / HTTP/1.0" 426 - 0 0 0 - "-" "-" "-" "-" "-" 20 | [2019-08-11T18:27:55.120Z] "OPTIONS / HTTP/1.0" 426 - 0 0 0 - "-" "-" "-" "-" "-" 21 | [2019-08-11T18:28:00.127Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 22 | [2019-08-11T18:28:00.173Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 23 | [2019-08-11T18:28:00.243Z] "GET /nice%20ports%2C/Tri%6Eity.txt%2ebak HTTP/1.0" 426 - 0 0 0 - "-" "-" "-" "-" "-" 24 | [2019-08-11T18:28:05.282Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 25 | [2019-08-11T18:28:05.293Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 26 | [2019-08-11T18:28:05.313Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 27 | [2019-08-11T18:28:05.383Z] "- - HTTP/1.1" 0 DC 0 0 0 - "-" "-" "-" "-" "-" 28 | [2019-08-12T06:54:00.858Z] "GET / HTTP/1.1" 200 - 0 5233 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-" "10.10.64.58:9901" "-" 29 | [2019-08-12T09:27:15.783Z] "GET / HTTP/1.1" 200 - 0 5233 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-" "10.10.64.58:9901" "-" 30 | [2019-08-12T09:27:17.315Z] "GET /config_dump HTTP/1.1" 200 - 0 9280 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-" "10.10.64.58:9901" "-" 31 | [2019-08-12T09:27:17.422Z] "GET /favicon.ico HTTP/1.1" 404 - 0 1121 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-" "10.10.64.58:9901" "-" 32 | [2019-08-12T09:27:42.680Z] "GET /clusters HTTP/1.1" 200 - 0 2784 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-" "10.10.64.58:9901" "-" 33 | [2019-08-12T09:27:46.591Z] "GET /config_dump HTTP/1.1" 200 - 0 9280 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-" "10.10.64.58:9901" "-" 34 | [2019-08-12T09:27:56.930Z] "GET /config_dump HTTP/1.1" 200 - 0 9280 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15" "-" "10.10.64.58:9901" "-" 35 | [2019-08-12T09:27:57.106Z] "GET /favicon.ico HTTP/1.1" 404 - 0 1121 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15" "-" "10.10.64.58:9901" "-" 36 | [2019-08-12T09:29:53.865Z] "GET /config_dump HTTP/1.1" 200 - 0 3833 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-" "10.10.64.58:9901" "-" 37 | [2019-08-12T09:30:31.245Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36" "-" "10.10.64.58:9901" "-" 38 | [2019-08-12T09:35:34.264Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 39 | [2019-08-12T09:35:34.818Z] "GET /favicon.ico HTTP/1.1" 404 - 0 1121 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 40 | [2019-08-12T09:40:10.305Z] "GET /config_dump HTTP/1.1" 200 - 0 4363 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 41 | [2019-08-12T09:41:12.296Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 42 | [2019-08-12T09:41:46.979Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 43 | [2019-08-12T09:42:00.604Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 44 | [2019-08-12T09:42:20.127Z] "GET /config_dump HTTP/1.1" 200 - 0 4363 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 45 | [2019-08-12T09:44:46.540Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 46 | [2019-08-12T09:59:13.508Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 47 | [2019-08-12T09:59:24.062Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 48 | [2019-08-12T09:59:34.651Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 49 | [2019-08-12T09:59:53.894Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 50 | [2019-08-12T10:00:11.840Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 51 | [2019-08-12T10:00:14.576Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 52 | [2019-08-12T10:00:15.481Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 53 | [2019-08-12T10:00:31.610Z] "GET /config_dump HTTP/1.1" 200 - 0 4363 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 54 | [2019-08-12T10:00:51.395Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 3 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 55 | [2019-08-12T10:00:52.813Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 56 | [2019-08-12T10:01:14.902Z] "GET /config_dump HTTP/1.1" 200 - 0 4363 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 57 | [2019-08-12T11:12:33.396Z] "GET /config_dump HTTP/1.1" 200 - 0 2694 1 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 58 | [2019-08-12T11:12:44.005Z] "GET /config_dump HTTP/1.1" 200 - 0 3788 0 - "10.255.3.3" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "10.10.64.58:9901" "-" 59 | [2019-08-16T08:59:47.387Z] "GET / HTTP/1.1" 200 - 0 5233 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "127.0.0.1:9901" "-" 60 | [2019-08-19T08:01:23.486Z] "GET /config_dump/ HTTP/1.1" 404 - 0 1121 15 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "127.0.0.1:9901" "-" 61 | [2019-08-19T08:01:23.805Z] "GET /favicon.ico HTTP/1.1" 404 - 0 1121 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "127.0.0.1:9901" "-" 62 | [2019-08-19T08:01:26.002Z] "GET / HTTP/1.1" 200 - 0 5233 1 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "127.0.0.1:9901" "-" 63 | [2019-08-19T08:01:27.264Z] "GET /config_dump HTTP/1.1" 200 - 0 9242 22 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" "-" "127.0.0.1:9901" "-" 64 | [2019-08-23T12:30:39.952Z] "GET / HTTP/1.1" 200 - 0 5233 2 - "172.17.0.1" "curl/7.54.0" "-" "127.0.0.1:9901" "-" 65 | [2019-08-23T12:30:48.855Z] "GET / HTTP/1.1" 200 - 0 5233 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "127.0.0.1:9901" "-" 66 | [2019-08-23T12:32:48.690Z] "GET /clusters HTTP/1.1" 200 - 0 5024 4 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "127.0.0.1:9901" "-" 67 | [2019-08-23T12:32:48.776Z] "GET /favicon.ico HTTP/1.1" 404 - 0 1121 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "127.0.0.1:9901" "-" 68 | [2019-08-30T06:34:14.468Z] "GET / HTTP/1.1" 200 - 0 5233 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 69 | [2019-08-30T06:34:16.246Z] "GET /clusters HTTP/1.1" 200 - 0 5024 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 70 | [2019-08-30T06:34:16.408Z] "GET /favicon.ico HTTP/1.1" 404 - 0 1121 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 71 | [2019-08-30T06:34:28.012Z] "GET /listeners HTTP/1.1" 200 - 0 23 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 72 | [2019-08-30T06:34:31.082Z] "GET /clusters HTTP/1.1" 200 - 0 5024 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 73 | [2019-08-30T08:29:44.003Z] "GET /clusters HTTP/1.1" 200 - 0 5009 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 74 | [2019-08-30T08:38:28.187Z] "GET /clusters HTTP/1.1" 200 - 0 5006 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 75 | [2019-08-30T08:38:30.763Z] "GET / HTTP/1.1" 200 - 0 5233 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 76 | [2019-08-30T08:38:32.295Z] "GET /clusters HTTP/1.1" 200 - 0 5006 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 77 | [2019-08-30T08:38:35.669Z] "GET /config_dump HTTP/1.1" 200 - 0 9021 1 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 78 | [2019-08-30T08:40:56.649Z] "GET / HTTP/1.1" 200 - 0 5233 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 79 | [2019-08-30T08:40:58.126Z] "GET /config_dump HTTP/1.1" 200 - 0 9021 1 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 80 | [2019-08-30T08:41:03.278Z] "GET /listeners HTTP/1.1" 200 - 0 23 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 81 | [2019-08-30T08:41:06.051Z] "GET /clusters HTTP/1.1" 200 - 0 5006 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "0.0.0.0:9901" "-" 82 | [2019-09-02T07:54:32.814Z] "GET / HTTP/1.1" 200 - 0 5233 1 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "127.0.0.1:9901" "-" 83 | [2019-09-02T07:54:35.752Z] "GET /config_dump HTTP/1.1" 200 - 0 2873 6 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "127.0.0.1:9901" "-" 84 | [2019-09-02T08:02:29.471Z] "GET /config_dump HTTP/1.1" 200 - 0 3608 1 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0" "-" "127.0.0.1:9901" "-" 85 | [2019-09-02T08:02:40.330Z] "GET /config_dump HTTP/1.1" 200 - 0 3608 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" "-" "127.0.0.1:9901" "-" 86 | [2019-09-02T08:02:40.715Z] "GET /favicon.ico HTTP/1.1" 404 - 0 1121 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" "-" "127.0.0.1:9901" "-" 87 | [2019-09-02T09:29:48.410Z] "GET /config_dump HTTP/1.1" 200 - 0 2700 1 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" "-" "127.0.0.1:9901" "-" 88 | [2019-09-02T10:07:47.993Z] "GET / HTTP/1.1" 200 - 0 5233 0 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" "-" "127.0.0.1:9901" "-" 89 | [2019-09-02T10:07:49.564Z] "GET /config_dump HTTP/1.1" 200 - 0 10791 2 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" "-" "127.0.0.1:9901" "-" 90 | [2019-09-02T10:11:29.730Z] "GET /config_dump HTTP/1.1" 200 - 0 12932 1 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" "-" "127.0.0.1:9901" "-" 91 | [2019-09-03T07:05:47.502Z] "GET /clusters HTTP/1.1" 200 - 0 5909 6 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" "-" "127.0.0.1:9901" "-" 92 | [2019-09-03T07:06:02.164Z] "GET /config_dump HTTP/1.1" 200 - 0 10468 11 - "172.17.0.1" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36" "-" "127.0.0.1:9901" "-" 93 | -------------------------------------------------------------------------------- /envoydev/xds/envoy-docker-run/run.sh: -------------------------------------------------------------------------------- 1 | IMAGE=lijiaocn/envoy:v1.11.0 2 | NAME=envoy-1.11.0 3 | 4 | if [ $# -ne 1 ];then 5 | echo "must choose one config file" 6 | exit 1 7 | fi 8 | 9 | config=$1 10 | 11 | docker rm -f $NAME 2>&1 1>/dev/null 12 | 13 | if [ `uname`="Darwin" ];then 14 | # docker run -idt --name $NAME -e loglevel=debug -p 9901:9901 -p 80-86:80-86 -v `pwd`/$config:/etc/envoy/envoy.yaml -v `pwd`/log:/var/log/envoy $IMAGE 15 | docker run -idt --name $NAME -p 9901:9901 -p 80-86:80-86 -v `pwd`/$config:/etc/envoy/envoy.yaml -v `pwd`/log:/var/log/envoy $IMAGE 16 | else 17 | docker run -idt --name $NAME -e loglevel=debug --network=host -v `pwd`/$config:/etc/envoy/envoy.yaml -v `pwd`/log:/var/log/envoy $IMAGE 18 | fi 19 | -------------------------------------------------------------------------------- /envoydev/xds/xds.go: -------------------------------------------------------------------------------- 1 | // Create: 2018/12/29 18:32:00 Change: 2019/09/02 17:44:34 2 | // FileName: waitgroup.go 3 | // Copyright (C) 2018 lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | "net" 11 | "time" 12 | 13 | api_v2 "github.com/envoyproxy/go-control-plane/envoy/api/v2" 14 | "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" 15 | "github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint" 16 | "github.com/envoyproxy/go-control-plane/envoy/api/v2/listener" 17 | "github.com/envoyproxy/go-control-plane/envoy/api/v2/route" 18 | http_router "github.com/envoyproxy/go-control-plane/envoy/config/filter/http/router/v2" 19 | http_conn_manager "github.com/envoyproxy/go-control-plane/envoy/config/filter/network/http_connection_manager/v2" 20 | discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v2" 21 | envoy_type "github.com/envoyproxy/go-control-plane/envoy/type" 22 | "github.com/envoyproxy/go-control-plane/pkg/cache" 23 | xds "github.com/envoyproxy/go-control-plane/pkg/server" 24 | "github.com/envoyproxy/go-control-plane/pkg/util" 25 | proto_type "github.com/gogo/protobuf/types" 26 | "github.com/golang/glog" 27 | "google.golang.org/grpc" 28 | ) 29 | 30 | type ADDR struct { 31 | Address string 32 | Port uint32 33 | } 34 | 35 | type NodeConfig struct { 36 | node *core.Node 37 | endpoints []cache.Resource //[]*api_v2.ClusterLoadAssignment 38 | clusters []cache.Resource //[]*api_v2.Cluster 39 | routes []cache.Resource //[]*api_v2.RouteConfiguration 40 | listeners []cache.Resource //[]*api_v2.Listener 41 | } 42 | 43 | //implement cache.NodeHash 44 | func (n NodeConfig) ID(node *core.Node) string { 45 | return node.GetId() 46 | } 47 | 48 | func Cluster_STATIC(name string, addrs []ADDR) *api_v2.Cluster { 49 | lbEndpoints := make([]*endpoint.LbEndpoint, 0) 50 | 51 | for _, addr := range addrs { 52 | // endpoint 地址 53 | hostIdentifier := &endpoint.LbEndpoint_Endpoint{ 54 | Endpoint: &endpoint.Endpoint{ 55 | Address: &core.Address{ 56 | Address: &core.Address_SocketAddress{ 57 | SocketAddress: &core.SocketAddress{ 58 | Protocol: core.TCP, 59 | Address: addr.Address, 60 | PortSpecifier: &core.SocketAddress_PortValue{ 61 | PortValue: addr.Port, 62 | }, 63 | }, 64 | }, 65 | }, 66 | }, 67 | } 68 | 69 | lbEndpoint := &endpoint.LbEndpoint{ 70 | HostIdentifier: hostIdentifier, 71 | } 72 | 73 | lbEndpoints = append(lbEndpoints, lbEndpoint) 74 | } 75 | 76 | // endpoints 分组,由多个 endpoint 组成 77 | localityLbEndpoints := &endpoint.LocalityLbEndpoints{ 78 | LbEndpoints: lbEndpoints, 79 | } 80 | 81 | endpoints := make([]*endpoint.LocalityLbEndpoints, 0) 82 | endpoints = append(endpoints, localityLbEndpoints) 83 | 84 | //cluster 的多个 endpoints 分组 85 | clusterLoadAssignment := &api_v2.ClusterLoadAssignment{ 86 | ClusterName: name, // endpoint 是静态配置,clustername可以为空 87 | Endpoints: endpoints, 88 | } 89 | 90 | timeout := 1 * time.Second 91 | 92 | // 使用静态 endpoints 的 cluster,类型为 v2.Cluster_STATIC 93 | cluster := &api_v2.Cluster{ 94 | Name: name, 95 | AltStatName: name, 96 | ClusterDiscoveryType: &api_v2.Cluster_Type{ 97 | Type: api_v2.Cluster_STATIC, 98 | }, 99 | EdsClusterConfig: nil, 100 | ConnectTimeout: &timeout, 101 | PerConnectionBufferLimitBytes: nil, //default 1MB 102 | LbPolicy: api_v2.Cluster_ROUND_ROBIN, 103 | LoadAssignment: clusterLoadAssignment, 104 | } 105 | 106 | return cluster 107 | } 108 | 109 | func EDS(cluster string, addrs []ADDR) *api_v2.ClusterLoadAssignment { 110 | 111 | lbEndpoints := make([]*endpoint.LbEndpoint, 0) 112 | 113 | for _, addr := range addrs { 114 | // endpoint 地址 115 | hostIdentifier := &endpoint.LbEndpoint_Endpoint{ 116 | Endpoint: &endpoint.Endpoint{ 117 | Address: &core.Address{ 118 | Address: &core.Address_SocketAddress{ 119 | SocketAddress: &core.SocketAddress{ 120 | Protocol: core.TCP, 121 | Address: addr.Address, 122 | PortSpecifier: &core.SocketAddress_PortValue{ 123 | PortValue: addr.Port, 124 | }, 125 | }, 126 | }, 127 | }, 128 | }, 129 | } 130 | 131 | lbEndpoint := &endpoint.LbEndpoint{ 132 | HostIdentifier: hostIdentifier, 133 | } 134 | 135 | lbEndpoints = append(lbEndpoints, lbEndpoint) 136 | } 137 | 138 | // 一个 endpoint 分组 139 | localityLbEndpoint := &endpoint.LocalityLbEndpoints{ 140 | LbEndpoints: lbEndpoints, 141 | } 142 | 143 | localityLbEndpoints := make([]*endpoint.LocalityLbEndpoints, 0) 144 | localityLbEndpoints = append(localityLbEndpoints, localityLbEndpoint) 145 | 146 | // 请求量过载时的处理策略 147 | dropOverLoad := &api_v2.ClusterLoadAssignment_Policy_DropOverload{ 148 | Category: "drop_policy1", 149 | DropPercentage: &envoy_type.FractionalPercent{ 150 | Numerator: 3, 151 | Denominator: envoy_type.FractionalPercent_HUNDRED, 152 | }, 153 | } 154 | 155 | dropOverLoads := make([]*api_v2.ClusterLoadAssignment_Policy_DropOverload, 0) 156 | dropOverLoads = append(dropOverLoads, dropOverLoad) 157 | 158 | // cluster 的多个 endpoints 分组 159 | point := &api_v2.ClusterLoadAssignment{ 160 | ClusterName: cluster, 161 | Endpoints: localityLbEndpoints, 162 | Policy: &api_v2.ClusterLoadAssignment_Policy{ 163 | DropOverloads: dropOverLoads, 164 | OverprovisioningFactor: &proto_type.UInt32Value{ 165 | Value: 140, 166 | }, 167 | }, 168 | } 169 | 170 | return point 171 | } 172 | 173 | func Cluster_EDS(name string, edsCluster []string, edsName string) *api_v2.Cluster { 174 | 175 | grpcServices := make([]*core.GrpcService, 0) 176 | 177 | for _, cluster := range edsCluster { 178 | // grpc 服务地址, envoy 中配置的 cluster,用于发现 endpoints 179 | grpcService := &core.GrpcService{ 180 | TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 181 | EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ 182 | ClusterName: cluster, 183 | }, 184 | }, 185 | } 186 | grpcServices = append(grpcServices, grpcService) 187 | } 188 | 189 | // eds 发现配置 190 | edsClusterConfig := &api_v2.Cluster_EdsClusterConfig{ 191 | EdsConfig: &core.ConfigSource{ 192 | ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 193 | ApiConfigSource: &core.ApiConfigSource{ 194 | ApiType: core.ApiConfigSource_GRPC, 195 | GrpcServices: grpcServices, 196 | }, 197 | }, 198 | }, 199 | ServiceName: edsName, 200 | } 201 | 202 | timeout := 1 * time.Second 203 | 204 | // 通过 eds 发现 endpoint 中的 cluster,类型为 Cluster_EDS 205 | cluster := &api_v2.Cluster{ 206 | Name: name, 207 | AltStatName: name, 208 | ClusterDiscoveryType: &api_v2.Cluster_Type{ 209 | Type: api_v2.Cluster_EDS, 210 | }, 211 | EdsClusterConfig: edsClusterConfig, 212 | ConnectTimeout: &timeout, 213 | LbPolicy: api_v2.Cluster_ROUND_ROBIN, 214 | } 215 | 216 | return cluster 217 | } 218 | 219 | func Listener_STATIC(name string, port uint32, host, prefix, toCluster string) *api_v2.Listener { 220 | 221 | // listener 主要由 监听地址 和 多个 filter 组成 222 | // 其中 filter 是最复杂的部分,它由多条 filter 链组成 223 | // 名为 HttpConnectionManager 的 network filter 中继续包含有 http filter 224 | 225 | // 到达监听地址的请求,经过多个filter处理,最终转发到给对应的 cluster 226 | 227 | // listener 的监听地址 228 | address := &core.Address{ 229 | Address: &core.Address_SocketAddress{ 230 | SocketAddress: &core.SocketAddress{ 231 | Protocol: core.TCP, 232 | Address: "0.0.0.0", 233 | PortSpecifier: &core.SocketAddress_PortValue{ 234 | PortValue: port, 235 | }, 236 | }, 237 | }, 238 | } 239 | 240 | // 一个 http route, 符合条件的请求转给对应的 cluster 241 | rt := &route.Route{ 242 | Match: &route.RouteMatch{ 243 | PathSpecifier: &route.RouteMatch_Prefix{ 244 | Prefix: prefix, 245 | }, 246 | CaseSensitive: &proto_type.BoolValue{ 247 | Value: false, 248 | }, 249 | }, 250 | Action: &route.Route_Route{ 251 | Route: &route.RouteAction{ 252 | ClusterSpecifier: &route.RouteAction_Cluster{ 253 | Cluster: toCluster, //转发到这个cluster 254 | }, 255 | HostRewriteSpecifier: &route.RouteAction_HostRewrite{ 256 | HostRewrite: host, 257 | }, 258 | }, 259 | }, 260 | } 261 | 262 | routes := make([]*route.Route, 0) 263 | routes = append(routes, rt) 264 | 265 | // route 在 virutualhost 中,virtualhost 指定了域名 266 | virtualHost := &route.VirtualHost{ 267 | Name: "local", 268 | Domains: []string{ 269 | host, 270 | }, 271 | Routes: routes, 272 | } 273 | 274 | virtualHosts := make([]*route.VirtualHost, 0) 275 | virtualHosts = append(virtualHosts, virtualHost) 276 | 277 | // 准备一个 http filter 278 | http_filter_router_ := &http_router.Router{ 279 | DynamicStats: &proto_type.BoolValue{ 280 | Value: true, 281 | }, 282 | } 283 | 284 | http_filter_router, err := util.MessageToStruct(http_filter_router_) 285 | if err != nil { 286 | glog.Error(err) 287 | return nil 288 | } 289 | 290 | httpFilter := &http_conn_manager.HttpFilter{ 291 | Name: "envoy.router", 292 | ConfigType: &http_conn_manager.HttpFilter_Config{ 293 | Config: http_filter_router, 294 | }, 295 | } 296 | 297 | httpFilters := make([]*http_conn_manager.HttpFilter, 0) 298 | httpFilters = append(httpFilters, httpFilter) 299 | 300 | // 包含 route 的 virtualhost 和 httpfilter 汇聚到 listener_filter 中 301 | listen_filter_http_conn_ := &http_conn_manager.HttpConnectionManager{ 302 | StatPrefix: "ingress_http", 303 | RouteSpecifier: &http_conn_manager.HttpConnectionManager_RouteConfig{ 304 | RouteConfig: &api_v2.RouteConfiguration{ 305 | Name: "None", 306 | VirtualHosts: virtualHosts, 307 | }, 308 | }, 309 | HttpFilters: httpFilters, 310 | } 311 | 312 | // ptypes.MarshalAny() 313 | listen_filter_http_conn, err := util.MessageToStruct(listen_filter_http_conn_) 314 | if err != nil { 315 | glog.Error(err) 316 | return nil 317 | } 318 | 319 | // listen_filter 被纳入最终的 filter 320 | filter := &listener.Filter{ 321 | Name: "envoy.http_connection_manager", 322 | ConfigType: &listener.Filter_Config{ 323 | Config: listen_filter_http_conn, 324 | }, 325 | } 326 | 327 | filters := make([]*listener.Filter, 0) 328 | filters = append(filters, filter) 329 | 330 | filterChain := &listener.FilterChain{ 331 | Filters: filters, 332 | } 333 | 334 | filterChains := make([]*listener.FilterChain, 0) 335 | filterChains = append(filterChains, filterChain) 336 | 337 | // 一个 listener 338 | lis := &api_v2.Listener{ 339 | Name: name, 340 | Address: address, 341 | FilterChains: filterChains, 342 | } 343 | 344 | return lis 345 | } 346 | 347 | func Route(name, host, prefix, toCluster string) *api_v2.RouteConfiguration { 348 | rt := &route.Route{ 349 | Match: &route.RouteMatch{ 350 | PathSpecifier: &route.RouteMatch_Prefix{ 351 | Prefix: prefix, 352 | }, 353 | CaseSensitive: &proto_type.BoolValue{ 354 | Value: false, 355 | }, 356 | }, 357 | Action: &route.Route_Route{ 358 | Route: &route.RouteAction{ 359 | ClusterSpecifier: &route.RouteAction_Cluster{ 360 | Cluster: toCluster, 361 | }, 362 | HostRewriteSpecifier: &route.RouteAction_HostRewrite{ 363 | HostRewrite: host, 364 | }, 365 | }, 366 | }, 367 | } 368 | 369 | routes := make([]*route.Route, 0) 370 | routes = append(routes, rt) 371 | 372 | virtualHost := &route.VirtualHost{ 373 | Name: "local", 374 | Domains: []string{ 375 | host, 376 | }, 377 | Routes: routes, 378 | } 379 | 380 | virtualHosts := make([]*route.VirtualHost, 0) 381 | virtualHosts = append(virtualHosts, virtualHost) 382 | 383 | routeConfig := &api_v2.RouteConfiguration{ 384 | Name: name, 385 | VirtualHosts: virtualHosts, 386 | } 387 | 388 | return routeConfig 389 | } 390 | 391 | func Listener_RDS(name string, port uint32, routeName string, rdsCluster []string) *api_v2.Listener { 392 | 393 | grpcServices := make([]*core.GrpcService, 0) 394 | for _, cluster := range rdsCluster { 395 | // grpc 服务地址在 envoy 中配置的 cluster,用于发现 endpoints 396 | grpcService := &core.GrpcService{ 397 | TargetSpecifier: &core.GrpcService_EnvoyGrpc_{ 398 | EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ 399 | ClusterName: cluster, 400 | }, 401 | }, 402 | } 403 | grpcServices = append(grpcServices, grpcService) 404 | } 405 | 406 | http_filter_router_ := &http_router.Router{ 407 | DynamicStats: &proto_type.BoolValue{ 408 | Value: true, 409 | }, 410 | } 411 | 412 | http_filter_router, err := util.MessageToStruct(http_filter_router_) 413 | if err != nil { 414 | glog.Error(err) 415 | return nil 416 | } 417 | 418 | listen_filter_http_conn_ := &http_conn_manager.HttpConnectionManager{ 419 | StatPrefix: "ingress_http", 420 | RouteSpecifier: &http_conn_manager.HttpConnectionManager_Rds{ 421 | Rds: &http_conn_manager.Rds{ 422 | RouteConfigName: routeName, //绑定的RDS 423 | ConfigSource: &core.ConfigSource{ 424 | ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{ 425 | ApiConfigSource: &core.ApiConfigSource{ 426 | ApiType: core.ApiConfigSource_GRPC, 427 | GrpcServices: grpcServices, 428 | }, 429 | }, 430 | }, 431 | }, 432 | }, 433 | HttpFilters: []*http_conn_manager.HttpFilter{ 434 | &http_conn_manager.HttpFilter{ 435 | Name: "envoy.router", 436 | ConfigType: &http_conn_manager.HttpFilter_Config{ 437 | Config: http_filter_router, 438 | }, 439 | }, 440 | }, 441 | } 442 | 443 | listen_filter_http_conn, err := util.MessageToStruct(listen_filter_http_conn_) 444 | if err != nil { 445 | glog.Error(err) 446 | return nil 447 | } 448 | 449 | lis := &api_v2.Listener{ 450 | Name: name, 451 | Address: &core.Address{ 452 | Address: &core.Address_SocketAddress{ 453 | SocketAddress: &core.SocketAddress{ 454 | Protocol: core.TCP, 455 | Address: "0.0.0.0", 456 | PortSpecifier: &core.SocketAddress_PortValue{ 457 | PortValue: port, 458 | }, 459 | }, 460 | }, 461 | }, 462 | FilterChains: []*listener.FilterChain{ 463 | &listener.FilterChain{ 464 | Filters: []*listener.Filter{ 465 | &listener.Filter{ 466 | Name: "envoy.http_connection_manager", 467 | ConfigType: &listener.Filter_Config{ 468 | Config: listen_filter_http_conn, 469 | }, 470 | }, 471 | }, 472 | }, 473 | }, 474 | } 475 | 476 | return lis 477 | } 478 | 479 | func Cluster_ADS(name string) *api_v2.Cluster { 480 | 481 | timeout := 1 * time.Second 482 | 483 | edsConfig := &core.ConfigSource{ 484 | ConfigSourceSpecifier: &core.ConfigSource_Ads{ 485 | Ads: &core.AggregatedConfigSource{}, //使用ADS 486 | }, 487 | } 488 | 489 | cluster := &api_v2.Cluster{ 490 | Name: name, 491 | AltStatName: name, 492 | ConnectTimeout: &timeout, 493 | ClusterDiscoveryType: &api_v2.Cluster_Type{ 494 | Type: api_v2.Cluster_EDS, 495 | }, 496 | LbPolicy: api_v2.Cluster_ROUND_ROBIN, 497 | EdsClusterConfig: &api_v2.Cluster_EdsClusterConfig{ 498 | EdsConfig: edsConfig, 499 | }, 500 | } 501 | return cluster 502 | } 503 | 504 | func Listener_ADS(name string, port uint32, routeName string) *api_v2.Listener { 505 | 506 | http_filter_router_ := &http_router.Router{ 507 | DynamicStats: &proto_type.BoolValue{ 508 | Value: true, 509 | }, 510 | } 511 | 512 | http_filter_router, err := util.MessageToStruct(http_filter_router_) 513 | if err != nil { 514 | glog.Error(err) 515 | return nil 516 | } 517 | 518 | httpFilter := &http_conn_manager.HttpFilter{ 519 | Name: "envoy.router", 520 | ConfigType: &http_conn_manager.HttpFilter_Config{ 521 | Config: http_filter_router, 522 | }, 523 | } 524 | 525 | httpFilters := make([]*http_conn_manager.HttpFilter, 0) 526 | httpFilters = append(httpFilters, httpFilter) 527 | 528 | listen_filter_http_conn_ := &http_conn_manager.HttpConnectionManager{ 529 | StatPrefix: "ingress_http", 530 | RouteSpecifier: &http_conn_manager.HttpConnectionManager_Rds{ 531 | Rds: &http_conn_manager.Rds{ 532 | RouteConfigName: routeName, 533 | ConfigSource: &core.ConfigSource{ 534 | ConfigSourceSpecifier: &core.ConfigSource_Ads{ 535 | Ads: &core.AggregatedConfigSource{}, //使用ADS 536 | }, 537 | }, 538 | }, 539 | }, 540 | HttpFilters: httpFilters, 541 | } 542 | 543 | listen_filter_http_conn, err := util.MessageToStruct(listen_filter_http_conn_) 544 | if err != nil { 545 | glog.Error(err) 546 | return nil 547 | } 548 | 549 | filter := &listener.Filter{ 550 | Name: "envoy.http_connection_manager", 551 | ConfigType: &listener.Filter_Config{ 552 | Config: listen_filter_http_conn, 553 | }, 554 | } 555 | 556 | filters := make([]*listener.Filter, 0) 557 | filters = append(filters, filter) 558 | 559 | filterChain := &listener.FilterChain{ 560 | Filters: filters, 561 | } 562 | 563 | filterChains := make([]*listener.FilterChain, 0) 564 | filterChains = append(filterChains, filterChain) 565 | 566 | socketAddr := &core.SocketAddress{ 567 | Protocol: core.TCP, 568 | Address: "0.0.0.0", 569 | PortSpecifier: &core.SocketAddress_PortValue{ 570 | PortValue: port, 571 | }, 572 | } 573 | 574 | addr := &core.Address{ 575 | Address: &core.Address_SocketAddress{ 576 | SocketAddress: socketAddr, 577 | }, 578 | } 579 | 580 | lis := &api_v2.Listener{ 581 | Name: name, 582 | Address: addr, 583 | FilterChains: filterChains, 584 | } 585 | 586 | return lis 587 | } 588 | 589 | func Update_SnapshotCache(s cache.SnapshotCache, n *NodeConfig, version string) { 590 | err := s.SetSnapshot(n.ID(n.node), cache.NewSnapshot(version, n.endpoints, n.clusters, n.routes, n.listeners)) 591 | if err != nil { 592 | glog.Error(err) 593 | } 594 | } 595 | 596 | func main() { 597 | snapshotCache := cache.NewSnapshotCache(false, NodeConfig{}, nil) 598 | server := xds.NewServer(snapshotCache, nil) 599 | grpcServer := grpc.NewServer() 600 | lis, _ := net.Listen("tcp", ":5678") 601 | 602 | discovery.RegisterAggregatedDiscoveryServiceServer(grpcServer, server) 603 | api_v2.RegisterEndpointDiscoveryServiceServer(grpcServer, server) 604 | api_v2.RegisterClusterDiscoveryServiceServer(grpcServer, server) 605 | api_v2.RegisterRouteDiscoveryServiceServer(grpcServer, server) 606 | api_v2.RegisterListenerDiscoveryServiceServer(grpcServer, server) 607 | 608 | go func() { 609 | if err := grpcServer.Serve(lis); err != nil { 610 | // error handling 611 | } 612 | }() 613 | 614 | node := &core.Node{ 615 | Id: "envoy-64.58", 616 | Cluster: "test", 617 | } 618 | 619 | node_config := &NodeConfig{ 620 | node: node, 621 | endpoints: []cache.Resource{}, //[]*api_v2.ClusterLoadAssignment 622 | clusters: []cache.Resource{}, //[]*api_v2.Cluster 623 | routes: []cache.Resource{}, //[]*api_v2.RouteConfiguration 624 | listeners: []cache.Resource{}, //[]*api_v2.Listener 625 | } 626 | 627 | input := "" 628 | 629 | { 630 | clusterName := "Cluster_With_Static_Endpoint" 631 | fmt.Printf("Enter to update version 1: %s", clusterName) 632 | _, _ = fmt.Scanf("\n", &input) 633 | 634 | var addrs []ADDR 635 | addrs = append(addrs, ADDR{ 636 | Address: "127.0.0.1", 637 | Port: 8081, 638 | }) 639 | cluster := Cluster_STATIC(clusterName, addrs) 640 | node_config.clusters = append(node_config.clusters, cluster) 641 | Update_SnapshotCache(snapshotCache, node_config, "1") 642 | fmt.Printf("ok") 643 | } 644 | 645 | { 646 | clusterName := "Cluster_With_Dynamic_Endpoint" 647 | 648 | fmt.Printf("\nEnter to update version 2: %s", clusterName) 649 | _, _ = fmt.Scanf("\n", &input) 650 | 651 | var addrs []ADDR 652 | addrs = append(addrs, ADDR{ 653 | Address: "127.0.0.1", 654 | Port: 8082, 655 | }) 656 | 657 | point := EDS(clusterName, addrs) 658 | node_config.endpoints = append(node_config.endpoints, point) 659 | 660 | var edsCluster []string 661 | edsCluster = append(edsCluster, "xds_cluster") //静态的配置的 cluster 662 | 663 | edsName := clusterName 664 | cluster := Cluster_EDS(clusterName, edsCluster, edsName) 665 | node_config.clusters = append(node_config.clusters, cluster) 666 | 667 | Update_SnapshotCache(snapshotCache, node_config, "2") 668 | fmt.Printf("ok") 669 | } 670 | 671 | { 672 | clusterName := "Cluster_With_ADS_Endpoint" 673 | fmt.Printf("\nEnter to update version 3: %s", clusterName) 674 | _, _ = fmt.Scanf("\n", &input) 675 | 676 | var addrs []ADDR 677 | addrs = append(addrs, ADDR{ 678 | Address: "127.0.0.1", 679 | Port: 8083, 680 | }) 681 | 682 | edsName := clusterName 683 | point := EDS(edsName, addrs) 684 | node_config.endpoints = append(node_config.endpoints, point) 685 | 686 | cluster := Cluster_ADS("Cluster_With_ADS_Endpoint") 687 | node_config.clusters = append(node_config.clusters, cluster) 688 | 689 | Update_SnapshotCache(snapshotCache, node_config, "3") 690 | fmt.Printf("ok") 691 | } 692 | 693 | { 694 | listenerName := "Listener_With_Static_Route" 695 | fmt.Printf("\nEnter to update version 4: %s", listenerName) 696 | _, _ = fmt.Scanf("\n", &input) 697 | 698 | clusterName := "Listener_With_Static_Route_Target_Cluster" 699 | var addrs []ADDR 700 | addrs = append(addrs, ADDR{ 701 | Address: "172.17.0.2", 702 | Port: 8080, 703 | }) 704 | cluster := Cluster_STATIC(clusterName, addrs) 705 | node_config.clusters = append(node_config.clusters, cluster) 706 | 707 | lis := Listener_STATIC(listenerName, 84, "echo.example", "/abc", clusterName) 708 | node_config.listeners = append(node_config.listeners, lis) 709 | 710 | Update_SnapshotCache(snapshotCache, node_config, "4") 711 | fmt.Printf("ok") 712 | } 713 | 714 | { 715 | listenerName := "Listener_With_Dynamic_Route" 716 | fmt.Printf("\nEnter to update version 5: %s", listenerName) 717 | _, _ = fmt.Scanf("\n", &input) 718 | 719 | clusterName := "Listener_With_Dynamic_Route_Target_Cluster" 720 | var addrs []ADDR 721 | addrs = append(addrs, ADDR{ 722 | Address: "172.17.0.2", 723 | Port: 8080, 724 | }) 725 | cluster := Cluster_STATIC(clusterName, addrs) 726 | node_config.clusters = append(node_config.clusters, cluster) 727 | 728 | routeName := "Listener_With_Dynamic_Route_Route" 729 | r := Route(routeName, "echo.example", "/123", clusterName) 730 | node_config.routes = append(node_config.routes, r) 731 | 732 | var rdsCluster []string 733 | rdsCluster = append(rdsCluster, "xds_cluster") //静态的配置的 cluster 734 | lis := Listener_RDS(listenerName, 85, routeName, rdsCluster) 735 | node_config.listeners = append(node_config.listeners, lis) 736 | 737 | Update_SnapshotCache(snapshotCache, node_config, "5") 738 | fmt.Printf("ok") 739 | } 740 | 741 | { 742 | listenerName := "Listener_With_ADS_Route" 743 | fmt.Printf("\nEnter to update version 6: %s", listenerName) 744 | _, _ = fmt.Scanf("\n", &input) 745 | 746 | clusterName := "Listener_With_ADS_Route_Target_Cluster" 747 | var addrs []ADDR 748 | addrs = append(addrs, ADDR{ 749 | Address: "172.17.0.2", 750 | Port: 8080, 751 | }) 752 | cluster := Cluster_STATIC(clusterName, addrs) 753 | node_config.clusters = append(node_config.clusters, cluster) 754 | 755 | routeName := "Listener_With_ADS_Route_Route" 756 | r := Route(routeName, "echo.example", "/a1b", clusterName) 757 | node_config.routes = append(node_config.routes, r) 758 | 759 | lis := Listener_ADS(listenerName, 86, routeName) 760 | node_config.listeners = append(node_config.listeners, lis) 761 | 762 | Update_SnapshotCache(snapshotCache, node_config, "6") 763 | fmt.Printf("ok") 764 | } 765 | 766 | fmt.Printf("\nEnter to exit: ") 767 | _, _ = fmt.Scanf("\n", &input) 768 | } 769 | 770 | //一个端口被多少个Listener使用,是否允许listener名称不同但端口相同 ? 771 | //一个 Listener可以使用多个filter,是否支持多个同类型的filter? 772 | //名为 envoy.http_connection_manager filter 中是否可以有多个http filter,是否支持多个同类型的http filter ? 773 | //名为 envoy.http_connection_manager filter 中是否可以有多个 VirtualHosts ? 774 | -------------------------------------------------------------------------------- /etcdclientv3/crud/crud.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 lijiaocn wechat: lijiaocn 2 | // 3 | // Distributed under terms of the GPL license. 4 | 5 | package main 6 | 7 | import ( 8 | "context" 9 | "encoding/json" 10 | "fmt" 11 | "time" 12 | 13 | "github.com/golang/glog" 14 | "go.etcd.io/etcd/clientv3" 15 | ) 16 | 17 | func toString(obj interface{}) (string, error) { 18 | bytes, err := json.Marshal(obj) 19 | if err != nil { 20 | return "", err 21 | } 22 | return string(bytes), nil 23 | } 24 | 25 | func PrintGetRespValue(resp *clientv3.GetResponse) { 26 | for i, v := range resp.Kvs { 27 | fmt.Printf("%d: %s %s\n\t%s\n", i, v.Key, v.Value, v.String()) 28 | } 29 | } 30 | 31 | // 写入ETCD 32 | func PUT(cli *clientv3.Client, key, val string, opts ...clientv3.OpOption) error { 33 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 34 | resp, err := cli.Put(ctx, key, val, opts...) 35 | cancel() 36 | if err != nil { 37 | return err 38 | } 39 | 40 | respStr, err := toString(resp) 41 | if err != nil { 42 | return err 43 | } 44 | 45 | fmt.Printf("PUT RESULT: %s\n", respStr) 46 | if resp.PrevKv != nil { 47 | fmt.Printf(">> prev key: %s value: %s\n", resp.PrevKv.Key, resp.PrevKv.Value) 48 | } 49 | fmt.Printf("\n") 50 | 51 | return nil 52 | } 53 | 54 | // 查询ETCD 55 | func GET(cli *clientv3.Client, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) { 56 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 57 | resp, err := cli.Get(ctx, key, opts...) 58 | cancel() 59 | return resp, err 60 | } 61 | 62 | func WATCH(cli *clientv3.Client, key string, opts ...clientv3.OpOption) (clientv3.WatchChan, error) { 63 | watchChan := cli.Watch(context.Background(), key, opts...) 64 | return watchChan, nil 65 | } 66 | 67 | func main() { 68 | 69 | config := clientv3.Config{ 70 | Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"}, 71 | DialTimeout: 5 * time.Second, 72 | } 73 | 74 | cli, err := clientv3.New(config) 75 | if err != nil { 76 | glog.Fatal(err.Error()) 77 | } 78 | 79 | defer func() { 80 | if err := cli.Close(); err != nil { 81 | glog.Error(err.Error()) 82 | } 83 | }() 84 | 85 | if err := PUT(cli, "/dir/sample_key", "sample_value123", clientv3.WithPrevKV()); err != nil { 86 | glog.Errorf(err.Error()) 87 | } 88 | 89 | if resp, err := GET(cli, "/dir/sample_key"); err != nil { 90 | glog.Errorf(err.Error()) 91 | } else { 92 | respStr, _ := toString(resp) 93 | fmt.Printf("GET RESULT: %s\n", respStr) 94 | fmt.Printf("> count: %d more: %v\n", resp.Count, resp.More) 95 | for i, v := range resp.Kvs { 96 | fmt.Printf(">> %d key: %s value: %s\n", i, v.Key, v.Value) 97 | } 98 | fmt.Printf("\n") 99 | } 100 | 101 | if resp, err := GET(cli, "/dir", clientv3.WithPrefix()); err != nil { 102 | glog.Errorf(err.Error()) 103 | } else { 104 | PrintGetRespValue(resp) 105 | } 106 | 107 | if watchChan, err := WATCH(cli, "/dir", clientv3.WithPrefix(), clientv3.WithPrevKV()); err != nil { 108 | glog.Errorf(err.Error()) 109 | } else { 110 | for { 111 | wr := <-watchChan 112 | if wrStr, err := toString(wr); err != nil { 113 | glog.Error(err.Error()) 114 | } else { 115 | fmt.Printf("WATCH RESULT: %s\n", wrStr) 116 | for i, v := range wr.Events { 117 | if v.Kv != nil { 118 | fmt.Printf("> %d type: %d key: %s value: %s ", i, v.Type, v.Kv.Key, v.Kv.Value) 119 | } 120 | if v.PrevKv != nil { 121 | fmt.Printf("pre value: %s\n", v.PrevKv.Value) 122 | } 123 | } 124 | fmt.Printf("\n") 125 | 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /etcdclientv3/election/election.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/10 15:58:00 Change: 2019/07/11 11:37:16 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "flag" 11 | "fmt" 12 | "log" 13 | "time" 14 | 15 | "context" 16 | 17 | "github.com/coreos/etcd/clientv3" 18 | "github.com/golang/glog" 19 | "go.etcd.io/etcd/clientv3/concurrency" 20 | ) 21 | 22 | func PrintGetRespValue(resp *clientv3.GetResponse) { 23 | for i, v := range resp.Kvs { 24 | fmt.Printf("%d: %s %s\n\t%s\n", i, v.Key, v.Value, v.String()) 25 | } 26 | } 27 | 28 | func main() { 29 | var node string 30 | flag.StringVar(&node, "name", "node1", "node name for election") 31 | 32 | flag.Parse() 33 | 34 | electprefix := "/testelection" 35 | config := clientv3.Config{ 36 | Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"}, 37 | DialTimeout: 5 * time.Second, 38 | } 39 | 40 | cli, err := clientv3.New(config) 41 | if err != nil { 42 | glog.Fatal(err.Error()) 43 | } 44 | 45 | defer func() { 46 | if err := cli.Close(); err != nil { 47 | glog.Error(err.Error()) 48 | } 49 | }() 50 | 51 | var s *concurrency.Session 52 | s, err = concurrency.NewSession(cli, concurrency.WithTTL(1)) 53 | if err != nil { 54 | log.Fatal(err) 55 | } 56 | defer s.Close() 57 | 58 | e := concurrency.NewElection(s, electprefix) 59 | 60 | // leader 61 | newleader := e.Observe(context.Background()) 62 | go func() { 63 | for { 64 | select { 65 | case resp := <-newleader: 66 | fmt.Printf("New Election Result:\n") 67 | PrintGetRespValue(&resp) 68 | } 69 | } 70 | }() 71 | 72 | //竞选 Leader,直到成为 Leader 函数才返回 73 | if err = e.Campaign(context.Background(), node); err != nil { 74 | glog.Fatalf("Campaign() returned non nil err: %s", err) 75 | } 76 | fmt.Printf("I'm leader") 77 | 78 | time.Sleep(5 * time.Minute) 79 | } 80 | -------------------------------------------------------------------------------- /ginusage/01quickstart/quickstart.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/19 17:46:00 Change: 2019/07/19 17:47:00 2 | // FileName: json_and_others.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import ( 10 | "net/http" 11 | "time" 12 | 13 | "github.com/gin-gonic/gin" 14 | ) 15 | 16 | func main() { 17 | r := gin.Default() 18 | r.GET("/ping", func(c *gin.Context) { 19 | c.JSON(200, gin.H{ 20 | "message": "pong", 21 | }) 22 | }) 23 | 24 | //r.Run() // listen and serve on 0.0.0.0:8080 25 | s := &http.Server{ 26 | Addr: ":8080", 27 | Handler: r, 28 | ReadTimeout: 10 * time.Second, 29 | WriteTimeout: 10 * time.Second, 30 | MaxHeaderBytes: 1 << 20, 31 | } 32 | s.ListenAndServe() 33 | } 34 | -------------------------------------------------------------------------------- /ginusage/02router/router.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | func echo(c *gin.Context) { 6 | c.JSON(200, gin.H{ 7 | "method": c.Request.Method, 8 | "uri": c.Request.URL.String(), 9 | }) 10 | } 11 | 12 | func main() { 13 | router := gin.Default() 14 | 15 | router.GET("/get", echo) 16 | router.POST("/post", echo) 17 | router.PUT("/put", echo) 18 | router.DELETE("/delete", echo) 19 | router.PATCH("/patch", echo) 20 | router.HEAD("/head", echo) 21 | router.OPTIONS("/option", echo) 22 | 23 | groupv1 := router.Group("/v1") 24 | { 25 | groupv1.GET("/hello", echo) 26 | } 27 | 28 | groupv2 := router.Group("/v1") 29 | { 30 | groupv2.GET("/hello", echo) 31 | } 32 | 33 | router.Run() 34 | } 35 | -------------------------------------------------------------------------------- /ginusage/03grouprouter/grouprouter.go: -------------------------------------------------------------------------------- 1 | // Create: 2019/07/22 10:50:00 Change: 2019/07/22 11:05:15 2 | // FileName: waitgroup.go 3 | // Copyright (C) 2019 lijiaocn wechat:lijiaocn 4 | // 5 | // Distributed under terms of the GPL license. 6 | 7 | package main 8 | 9 | import "github.com/gin-gonic/gin" 10 | 11 | type A struct { 12 | Value int 13 | } 14 | 15 | var a A 16 | 17 | func SetA(c *gin.Context) { 18 | a.Value = 3 19 | c.JSON(200, a) 20 | } 21 | 22 | func GetA(c *gin.Context) { 23 | c.JSON(200, a) 24 | } 25 | 26 | func main() { 27 | router := gin.Default() 28 | 29 | // curl 127.0.0.1:8080/v1/a 30 | v1 := router.Group("/v1") 31 | { 32 | v1.GET("/a", GetA) 33 | v1.POST("/a", SetA) 34 | } 35 | 36 | router.Run(":8080") 37 | } 38 | -------------------------------------------------------------------------------- /ginusage/04paraminquery/paraminquery.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func query(c *gin.Context) { 10 | name := c.DefaultQuery("name", "Guest") 11 | age := c.Query("age") 12 | 13 | c.String(http.StatusOK, "%s is %s years\n", name, age) 14 | } 15 | 16 | func queryArray(c *gin.Context) { 17 | ids := c.QueryArray("ids") 18 | c.JSON(http.StatusOK, gin.H{ 19 | "ids": ids, 20 | }) 21 | } 22 | 23 | func queryMap(c *gin.Context) { 24 | ids := c.QueryMap("ids") 25 | c.JSON(http.StatusOK, gin.H{ 26 | "ids": ids, 27 | }) 28 | } 29 | 30 | type UserInfo struct { 31 | Name string `form:"name"` 32 | Age int `form:"age"` 33 | Message []string `form:"message"` 34 | MoreInfo map[string]string `form:"moreinfo"` 35 | } 36 | 37 | func queryBind(c *gin.Context) { 38 | var userInfo UserInfo 39 | c.BindQuery(&userInfo) 40 | //gin 1.5 的 BindQuery 似乎不支持 map,单独获取 41 | userInfo.MoreInfo = c.QueryMap("moreinfo") 42 | c.JSON(http.StatusOK, userInfo) 43 | } 44 | 45 | func main() { 46 | router := gin.Default() 47 | // curl 127.0.0.1:8080/query?name=xiaoming&age=11 48 | router.GET("/query", query) 49 | // curl "127.0.0.1:8080/arr?ids=A&ids=B" 50 | router.GET("/arr", queryArray) 51 | // curl "127.0.0.1:8080/map?ids[a]=1234&ids[b]=hello" 52 | router.GET("/map", queryMap) 53 | // curl "127.0.0.1:8080/bind?name=xiaoming&age=11&message=hello1&message=hello2&moreinfo[country]=china&moreinfo[hobby]=football" 54 | router.GET("/bind", queryBind) 55 | 56 | router.Run() 57 | } 58 | -------------------------------------------------------------------------------- /ginusage/05paraminheader/paraminheader.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func header(c *gin.Context) { 10 | token := c.GetHeader("TOKEN") 11 | c.JSON(http.StatusOK, gin.H{ 12 | "TOKEN": token, 13 | }) 14 | } 15 | 16 | type Token struct { 17 | Token string `header:"token"` 18 | } 19 | 20 | func headerBind(c *gin.Context) { 21 | var token Token 22 | c.BindHeader(&token) 23 | c.JSON(http.StatusOK, token) 24 | } 25 | 26 | func main() { 27 | r := gin.Default() 28 | // curl -H "TOKEN: 123456" 127.0.0.1:8080/header 29 | r.GET("/header", header) 30 | // curl -H "TOKEN: 123456" 127.0.0.1:8080/header/bind 31 | r.GET("/header/bind", headerBind) 32 | r.Run() 33 | } 34 | -------------------------------------------------------------------------------- /ginusage/06paraminpath/paraminpath.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func userName(c *gin.Context) { 10 | name := c.Param("name") 11 | c.String(http.StatusOK, "Hello %s\n", name) 12 | } 13 | 14 | func userNameAction(c *gin.Context) { 15 | name := c.Param("name") 16 | action := c.Param("action") 17 | c.String(http.StatusOK, "%s is %s\n", name, action) 18 | } 19 | 20 | type UserInfo struct { 21 | Name string `uri:"name"` 22 | Action string `uri:"action"` 23 | } 24 | 25 | func bindURI(c *gin.Context) { 26 | var userInfo UserInfo 27 | c.BindUri(&userInfo) 28 | c.JSON(http.StatusOK, userInfo) 29 | } 30 | 31 | func main() { 32 | router := gin.Default() 33 | 34 | // curl 127.0.0.1:8080/user/xiaoming 35 | // :name 必须存在 36 | // 匹配 /user/NAME 37 | // 不匹配 /user 或者 /user/ 38 | router.GET("/user/:name", userName) 39 | 40 | // curl 127.0.0.1:8080/user/xiaoming/run 41 | // *action 是可选的 42 | // 匹配 /user/NAME/ 43 | // 匹配 /user/NAME/ACTION 44 | // 如果 /user/NAME 没有对应的 router,重定向到 /user/NAME/ 45 | router.GET("/user/:name/*action", userNameAction) 46 | 47 | // curl -X POST 127.0.0.1:8080/user/xiaoming/run 48 | // POST 也可以使用路径参数 49 | router.POST("/user/:name/*action", userNameAction) 50 | 51 | // curl 127.0.0.1:8080/bind/user/xiaoming/run 52 | router.GET("/bind/user/:name/*action", bindURI) 53 | 54 | router.Run() 55 | } 56 | -------------------------------------------------------------------------------- /ginusage/07parampost/form/postform.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func postForm(c *gin.Context) { 10 | message := c.PostForm("message") 11 | name := c.DefaultPostForm("name", "guest") 12 | c.String(http.StatusOK, "%s %s", name, message) 13 | } 14 | 15 | func postFormMap(c *gin.Context) { 16 | ids := c.PostFormMap("ids") 17 | c.JSON(http.StatusOK, gin.H{ 18 | "ids": ids, 19 | }) 20 | } 21 | 22 | func postFormArray(c *gin.Context) { 23 | ids := c.PostFormArray("ids") 24 | c.JSON(http.StatusOK, gin.H{ 25 | "ids": ids, 26 | }) 27 | } 28 | 29 | type UserInfo struct { 30 | Name string `form:"name"` 31 | Age int `form:"age"` 32 | Message []string `form:"message"` 33 | MoreInfo map[string]string `form:"moreinfo"` 34 | } 35 | 36 | func postBind(c *gin.Context) { 37 | var userInfo UserInfo 38 | c.ShouldBind(&userInfo) 39 | //gin 1.5 的 ShouldBind 似乎不支持 map,单独读取 map 40 | userInfo.MoreInfo = c.PostFormMap("moreinfo") 41 | c.JSON(http.StatusOK, userInfo) 42 | } 43 | 44 | func main() { 45 | router := gin.Default() 46 | 47 | // curl -XPOST 127.0.0.1:8080/form -d "name=xiaoming&message=welcome!" 48 | router.POST("/form", postForm) 49 | 50 | // curl -XPOST 127.0.0.1:8080/map -d "ids[first]=100&ids[second]=200" 51 | router.POST("/map", postFormMap) 52 | 53 | // curl -XPOST 127.0.0.1:8080/map -d "ids=100&ids=200" 54 | router.POST("/arr", postFormArray) 55 | 56 | // curl -XPOST 127.0.0.1:8080/bind -d "name=xiaoming&age=11&message=hello1&message=hello2&moreinfo[country]=china&moreinfo[hobby]=football" 57 | router.POST("/bind", postBind) 58 | 59 | router.Run() 60 | } 61 | -------------------------------------------------------------------------------- /ginusage/07parampost/json_and_others/json_and_others.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 lijiaocn wechat: lijiaocn 2 | // 3 | // Distributed under terms of the GPL license. 4 | 5 | package main 6 | 7 | import ( 8 | "net/http" 9 | 10 | "github.com/gin-gonic/gin" 11 | ) 12 | 13 | type Login struct { 14 | User string `form:"user" json:"user" xml:"user" binding:"required"` 15 | Password string `form:"password" json:"password" xml:"password" binding:"required" ` 16 | } 17 | 18 | func bindJSON(c *gin.Context) { 19 | var login Login 20 | if err := c.ShouldBindJSON(&login); err != nil { 21 | c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) 22 | return 23 | } 24 | c.JSON(http.StatusOK, login) 25 | } 26 | 27 | func bindXML(c *gin.Context) { 28 | var login Login 29 | if err := c.ShouldBindXML(&login); err != nil { 30 | c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) 31 | return 32 | } 33 | c.JSON(http.StatusOK, login) 34 | } 35 | 36 | func bindALL(c *gin.Context) { 37 | var login Login 38 | if err := c.ShouldBind(&login); err != nil { 39 | c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) 40 | return 41 | } 42 | c.JSON(http.StatusOK, login) 43 | } 44 | 45 | func main() { 46 | router := gin.Default() 47 | 48 | // 几个 modelbind 函数的用法 49 | // c.ShouldBindQuery() 只解析 GET 参数 50 | // c.ShouldBind() 解析 GET 和 POST 数据 51 | // c.ShouldBindUri() 解析路径参数 52 | // c.ShouldBindHeader() 解析请求头 53 | 54 | // curl -X POST 127.0.0.1:8080/loginjson -d '{"user": "lijiao", "password":"123"}' 55 | router.POST("/loginjson", bindJSON) 56 | 57 | // curl -X POST 127.0.0.1:8080/loginxml \ 58 | // -d 'user123 ' 59 | router.POST("/loginxml", bindXML) 60 | 61 | // c.ShouldBind() 根据 content-type 选择合适的反序列化方式 62 | // curl -X POST 127.0.0.1:8080/loginform -H 'content-type: application/xml' \ 63 | // -d 'user123 ' 64 | // curl -X POST 127.0.0.1:8080/loginform -H 'content-type: application/json' \ 65 | // -d '{"user": "lijiao", "password":"123"}' 66 | // curl -X POST 127.0.0.1:8080/loginform -d "user=lijiao&password=123" 67 | router.POST("/loginform", bindALL) 68 | 69 | router.Run(":8080") 70 | } 71 | -------------------------------------------------------------------------------- /ginusage/08middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | func CustormMiddleWare() gin.HandlerFunc { 12 | return func(c *gin.Context) { 13 | t := time.Now() 14 | c.Next() //继续执行其它中间件 15 | latency := time.Since(t) 16 | status := c.Writer.Status() 17 | log.Println(latency, status) 18 | } 19 | } 20 | 21 | func main() { 22 | router := gin.New() 23 | 24 | //全局中间件:日志写入 gin.DefaultWriter = os.Stdout 25 | router.Use(gin.Logger()) 26 | router.Use(CustormMiddleWare()) 27 | 28 | //全局中间件:如果发生 panic 恢复,并回复 500 29 | router.Use(gin.Recovery()) 30 | 31 | //作用于当前路由的中间件 32 | router.GET("/echo", func(c *gin.Context) { 33 | c.Set("middleware1", "ok") 34 | }, func(c *gin.Context) { 35 | c.Set("middleware2", "ok") 36 | }, func(c *gin.Context) { 37 | resp := gin.H{} 38 | if v, ok := c.Get("middleware1"); ok { 39 | resp["middleware1"] = v 40 | } 41 | if v, ok := c.Get("middleware2"); ok { 42 | resp["middleware2"] = v 43 | } 44 | resp["path"] = "/echo" 45 | c.JSON(http.StatusOK, resp) 46 | }) 47 | 48 | //作用于 group 的中间件 49 | root := router.Group("/") 50 | root.Use(func(c *gin.Context) { 51 | c.Set("middleware3", "ok") 52 | }) 53 | { 54 | root.GET("/a", func(c *gin.Context) { 55 | resp := gin.H{} 56 | if v, ok := c.Get("middleware3"); ok { 57 | resp["middleware3"] = v 58 | } 59 | resp["path"] = "/a" 60 | c.JSON(http.StatusOK, resp) 61 | }) 62 | 63 | root.GET("/b", func(c *gin.Context) { 64 | resp := gin.H{} 65 | if v, ok := c.Get("middleware3"); ok { 66 | resp["middleware3"] = v 67 | } 68 | resp["path"] = "/b" 69 | c.JSON(http.StatusOK, resp) 70 | }) 71 | } 72 | 73 | router.Run() 74 | } 75 | -------------------------------------------------------------------------------- /ginusage/08response/response.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | func stringResp(c *gin.Context) { 10 | c.String(http.StatusOK, "This is a string") 11 | return 12 | } 13 | 14 | type UserInfo struct { 15 | Name string `json:"name"` 16 | Age int `json:"age"` 17 | Messages []string `json:"messages"` 18 | Attr map[string]string `json:"attr"` 19 | } 20 | 21 | var userInfo *UserInfo 22 | 23 | func jsonResp(c *gin.Context) { 24 | c.JSON(http.StatusOK, userInfo) 25 | return 26 | } 27 | 28 | func yamlResp(c *gin.Context) { 29 | c.YAML(http.StatusOK, userInfo) 30 | return 31 | } 32 | func xmlResp(c *gin.Context) { 33 | c.XML(http.StatusOK, userInfo) 34 | return 35 | } 36 | 37 | //func protobufResp(c *gin.Context) { 38 | // c.ProtoBuf(http.StatusOK, userInfo) 39 | // return 40 | //} 41 | 42 | func main() { 43 | userInfo = &UserInfo{ 44 | Name: "xiaoming", 45 | Age: 13, 46 | Messages: []string{"Welcome1", "Welcome2", "Welcome3"}, 47 | Attr: map[string]string{ 48 | "hobby": "footbool", 49 | "country": "china", 50 | }, 51 | } 52 | 53 | r := gin.Default() 54 | 55 | r.GET("/string", stringResp) 56 | r.GET("/json", jsonResp) 57 | r.GET("/yaml", yamlResp) 58 | r.GET("/xml", xmlResp) 59 | //TODO: 60 | // protobuf 61 | // header 62 | // data 63 | // file 64 | // redirect 65 | r.Run() 66 | } 67 | -------------------------------------------------------------------------------- /ginusage/09log/logset.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gin-gonic/gin" 6 | "io" 7 | "log" 8 | "net/http" 9 | "os" 10 | "time" 11 | ) 12 | 13 | func main() { 14 | gin.ForceConsoleColor() 15 | //gin.DisableConsoleColor() 16 | 17 | f, _ := os.Create("/tmp/gin.log") 18 | gin.DefaultWriter = io.MultiWriter(f) 19 | 20 | gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) { 21 | log.Printf("endpoint %v %v %v %v", httpMethod, absolutePath, handlerName, nuHandlers) 22 | } 23 | 24 | router := gin.New() 25 | router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { 26 | return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n", 27 | param.ClientIP, 28 | param.TimeStamp.Format(time.RFC1123), 29 | param.Method, 30 | param.Path, 31 | param.Request.Proto, 32 | param.StatusCode, 33 | param.Latency, 34 | param.Request.UserAgent(), 35 | param.ErrorMessage, 36 | ) 37 | })) 38 | router.Use(gin.Recovery()) 39 | 40 | router.GET("/echo", func(c *gin.Context) { 41 | c.String(http.StatusOK, "/echo") 42 | }) 43 | 44 | router.Run() 45 | } 46 | -------------------------------------------------------------------------------- /ginusage/09upload/upload.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | router := gin.Default() 10 | 11 | // curl -XPOST http://localhost:8080/upload/one -H "Content-Type: multipart/form-data" -F "file=@/tmp/file.txt" 12 | router.POST("/upload/one", func(c *gin.Context) { 13 | file, err := c.FormFile("file") 14 | if err != nil { 15 | c.String(http.StatusBadRequest, "request error: %s", err.Error()) 16 | return 17 | } 18 | if err := c.SaveUploadedFile(file, "/tmp/"+file.Filename+".saved"); err != nil { 19 | c.String(http.StatusInternalServerError, "internal error: %s", err.Error()) 20 | return 21 | } 22 | c.String(http.StatusOK, "received: %s", file.Filename) 23 | }) 24 | 25 | // curl -XPOST http://localhost:8080/upload/many -H "Content-Type: multipart/form-data" -F "upload[]=@/tmp/file1.txt" -F "upload[]=@/tmp/file2.txt" 26 | router.POST("/upload/many", func(c *gin.Context) { 27 | form, err := c.MultipartForm() 28 | if err != nil { 29 | c.String(http.StatusBadRequest, "request error: %s", err.Error()) 30 | return 31 | } 32 | files := form.File["upload[]"] 33 | 34 | received := gin.H{} 35 | failed := gin.H{} 36 | 37 | for _, file := range files { 38 | if err := c.SaveUploadedFile(file, "/tmp/"+file.Filename+".saved"); err != nil { 39 | failed[file.Filename] = err.Error() 40 | continue 41 | } 42 | received[file.Filename] = "ok" 43 | } 44 | c.JSON(http.StatusOK, gin.H{ 45 | "received": received, 46 | "failed": failed, 47 | }) 48 | }) 49 | 50 | router.Run() 51 | } 52 | -------------------------------------------------------------------------------- /ginusage/11validator/validator.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/gin-gonic/gin/binding" 6 | "gopkg.in/go-playground/validator.v8" 7 | "net/http" 8 | "reflect" 9 | "time" 10 | ) 11 | 12 | type Booking struct { 13 | //指定校验函数: bookabledate 14 | CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"` 15 | CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"` 16 | } 17 | 18 | type User struct { 19 | FirstName string `json:"fname"` 20 | LastName string `json:"lname""` 21 | Email string `bingding: "required,email"` 22 | } 23 | 24 | func bookabledate(v *validator.Validate, topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldtype reflect.Type, fieldKind reflect.Kind, param string) bool { 25 | if date, ok := field.Interface().(time.Time); ok { 26 | today := time.Now() 27 | if today.After(date) { 28 | return false 29 | } 30 | } 31 | return true 32 | } 33 | 34 | func main() { 35 | // 有问题,没通过,待查 36 | route := gin.Default() 37 | if v, ok := binding.Validator.Engine().(*validator.Validate); ok { 38 | //master分支中的 func 定义发生了变换,这里是 1.5.0 中的用法 39 | v.RegisterValidation("bookabledate", bookabledate) 40 | //Struct 级别的校验,该写法对于 1.5.0 不生效 41 | v.RegisterStructValidation(func(v *validator.Validate, structLevel *validator.StructLevel) { 42 | user := structLevel.CurrentStruct.Interface().(User) 43 | 44 | structLevel.ReportError(reflect.ValueOf(user.FirstName), "FirstName", "fname", "fnameorlname") 45 | if len(user.FirstName) == 0 && len(user.LastName) == 0 { 46 | structLevel.ReportError(reflect.ValueOf(user.FirstName), "FirstName", "fname", "fnameorlname") 47 | structLevel.ReportError(reflect.ValueOf(user.LastName), "LastName", "lname", "fnameorlname") 48 | } 49 | }, &User{}) 50 | } 51 | 52 | route.POST("/user", func(c *gin.Context) { 53 | var u User 54 | if err := c.ShouldBindJSON(&u); err != nil { 55 | c.JSON(http.StatusBadRequest, gin.H{ 56 | "message": "User validation failed", 57 | "error": err.Error(), 58 | }) 59 | return 60 | } 61 | c.JSON(http.StatusOK, &u) 62 | }) 63 | route.GET("/bookable", func(c *gin.Context) { 64 | var b Booking 65 | if err := c.ShouldBindWith(&b, binding.Query); err != nil { 66 | c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) 67 | return 68 | } 69 | }) 70 | route.Run() 71 | } 72 | -------------------------------------------------------------------------------- /ginusage/12render/render.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | route := gin.Default() 10 | 11 | var msg struct { 12 | Name string `json:"user"` 13 | Message string `json:"message"` 14 | Number int `json: "number"` 15 | } 16 | msg.Name = "lijiao,中国" 17 | msg.Message = "hello" 18 | 19 | route.GET("/json", func(c *gin.Context) { 20 | c.JSON(http.StatusOK, msg) 21 | }) 22 | 23 | route.GET("/securejson", func(c *gin.Context) { 24 | c.SecureJSON(http.StatusOK, msg) 25 | }) 26 | 27 | // curl "127.0.0.1:8080/jsonp?callback=x" 28 | // x({"user":"lijiao","message":"hello","Number":0});% 29 | route.GET("/jsonp", func(c *gin.Context) { 30 | c.JSONP(http.StatusOK, msg) 31 | }) 32 | 33 | route.GET("/asciijson", func(c *gin.Context) { 34 | c.AsciiJSON(http.StatusOK, msg) 35 | }) 36 | 37 | route.GET("/purejson", func(c *gin.Context) { 38 | c.PureJSON(http.StatusOK, msg) 39 | }) 40 | 41 | route.GET("/xml", func(c *gin.Context) { 42 | c.XML(http.StatusOK, gin.H{"message": "hello", "number": 10}) 43 | }) 44 | 45 | route.GET("/yaml", func(c *gin.Context) { 46 | c.YAML(http.StatusOK, msg) 47 | }) 48 | 49 | route.GET("/protobuf", func(c *gin.Context) { 50 | c.ProtoBuf(http.StatusOK, msg) 51 | }) 52 | 53 | route.Run() 54 | } 55 | -------------------------------------------------------------------------------- /ginusage/13serving/serving.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | route := gin.Default() 10 | 11 | route.Static("/static", "/tmp/static") 12 | route.StaticFS("/static2", http.Dir("/tmp/static2")) 13 | route.StaticFile("/file", "/tmp/static/file.txt") 14 | 15 | route.GET("/stream", func(c *gin.Context) { 16 | resp, err := http.Get("https://www.lijiaocn.com/money/img/self.jpg") 17 | if err != nil || resp.StatusCode != http.StatusOK { 18 | c.Status(http.StatusServiceUnavailable) 19 | return 20 | } 21 | reader := resp.Body 22 | contentLength := resp.ContentLength 23 | contentType := resp.Header.Get("Content-Type") 24 | 25 | extraHeaders := map[string]string{ 26 | "Content-Disposition": `attachment; filename="gopher.png"`, 27 | } 28 | 29 | c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders) 30 | }) 31 | route.Run() 32 | } 33 | -------------------------------------------------------------------------------- /ginusage/13serving/static/1.txt: -------------------------------------------------------------------------------- 1 | 111111 2 | -------------------------------------------------------------------------------- /ginusage/13serving/static/file.txt: -------------------------------------------------------------------------------- 1 | data in file.txt 2 | -------------------------------------------------------------------------------- /ginusage/13serving/static/static: -------------------------------------------------------------------------------- 1 | /tmp/static -------------------------------------------------------------------------------- /ginusage/13serving/static2/2.txt: -------------------------------------------------------------------------------- 1 | 222222 2 | -------------------------------------------------------------------------------- /ginusage/13serving/static2/static2: -------------------------------------------------------------------------------- 1 | /tmp/static2 -------------------------------------------------------------------------------- /ginusage/14render/render.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | route := gin.Default() 10 | route.LoadHTMLFiles("/tmp/templates/index.tmpl") 11 | route.LoadHTMLGlob("/tmp/templates/**/*") 12 | route.GET("/index", func(c *gin.Context) { 13 | c.HTML(http.StatusOK, "index.tmpl", gin.H{ 14 | "title": "lijiaocn.com", 15 | }) 16 | }) 17 | route.GET("/posts/index", func(c *gin.Context) { 18 | c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{ 19 | "title": "lijiaocn.com", 20 | }) 21 | }) 22 | route.GET("/redirect", func(c *gin.Context) { 23 | c.Redirect(http.StatusMovedPermanently, "https://wwww.lijiaocn.com") 24 | }) 25 | route.Run() 26 | } 27 | -------------------------------------------------------------------------------- /ginusage/14render/templates/index.tmpl: -------------------------------------------------------------------------------- 1 | 2 |

{{ .title }}

3 | -------------------------------------------------------------------------------- /ginusage/14render/templates/posts/index.tmpl: -------------------------------------------------------------------------------- 1 | {{ define "posts/index.tmpl" }} 2 | 3 |

{{ .title }}

4 |

Using posts/index.tmpl

5 | 6 | {{ end }} -------------------------------------------------------------------------------- /ginusage/15goroutine/goroutine.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "log" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | route := gin.Default() 11 | 12 | route.GET("/async", func(c *gin.Context) { 13 | cCp := c.Copy() //启动协程,必须重新拷贝一份 14 | go func() { 15 | time.Sleep(5 * time.Second) 16 | log.Println("Done: " + cCp.Request.URL.Path) 17 | }() 18 | }) 19 | 20 | route.GET("/sync", func(c *gin.Context) { 21 | time.Sleep(5 * time.Second) 22 | log.Println("Done: " + c.Request.URL.Path) 23 | }) 24 | 25 | route.Run() 26 | } 27 | -------------------------------------------------------------------------------- /ginusage/16tls/lets.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/autotls" 5 | "github.com/gin-gonic/gin" 6 | "net/http" 7 | ) 8 | 9 | func main() { 10 | r := gin.Default() 11 | 12 | r.GET("/ping", func(c *gin.Context) { 13 | c.String(http.StatusOK, "pong") 14 | }) 15 | 16 | autotls.Run(r, "example1.com", "example2.com") 17 | } 18 | -------------------------------------------------------------------------------- /ginusage/17multiserver/multiserver.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "golang.org/x/sync/errgroup" 6 | "log" 7 | "net/http" 8 | ) 9 | 10 | func router01() http.Handler { 11 | e := gin.New() 12 | e.Use(gin.Recovery()) 13 | e.GET("/", func(c *gin.Context) { 14 | c.String(http.StatusOK, "Welcome server 01") 15 | }) 16 | return e 17 | } 18 | 19 | func router02() http.Handler { 20 | e := gin.New() 21 | e.Use(gin.Recovery()) 22 | e.GET("/", func(c *gin.Context) { 23 | c.String(http.StatusOK, "Welcome server 02") 24 | }) 25 | return e 26 | } 27 | 28 | func main() { 29 | g := errgroup.Group{} 30 | 31 | server01 := &http.Server{ 32 | Addr: ":8080", 33 | Handler: router01(), 34 | } 35 | 36 | server02 := &http.Server{ 37 | Addr: ":8081", 38 | Handler: router02(), 39 | } 40 | 41 | g.Go(func() error { 42 | err := server01.ListenAndServe() 43 | if err != nil && err != http.ErrServerClosed { 44 | log.Fatal(err) 45 | } 46 | return err 47 | }) 48 | 49 | g.Go(func() error { 50 | err := server02.ListenAndServe() 51 | if err != nil && err != http.ErrServerClosed { 52 | log.Fatal(err) 53 | } 54 | return err 55 | }) 56 | 57 | if err := g.Wait(); err != nil { 58 | log.Fatal(err) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ginusage/18graceful/graceful.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "github.com/gin-gonic/gin" 6 | "log" 7 | "net/http" 8 | "os" 9 | "os/signal" 10 | "syscall" 11 | "time" 12 | ) 13 | 14 | func main() { 15 | route := gin.Default() 16 | route.GET("/", func(c *gin.Context) { 17 | time.Sleep(5 * time.Second) 18 | c.String(http.StatusOK, "gin server") 19 | }) 20 | 21 | server := &http.Server{ 22 | Addr: ":8080", 23 | Handler: route, 24 | } 25 | 26 | go func() { 27 | if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { 28 | log.Fatal("listen error:", err.Error()) 29 | } 30 | }() 31 | 32 | quit := make(chan os.Signal) 33 | 34 | signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) 35 | <-quit 36 | log.Println("Shutdown Server") 37 | 38 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 39 | defer cancel() 40 | 41 | if err := server.Shutdown(ctx); err != nil { 42 | log.Fatal("Server Shutdown: ", err.Error()) 43 | } 44 | 45 | select { 46 | case <-ctx.Done(): 47 | log.Println("timeout of 5 seconds") 48 | } 49 | log.Println("Server exiting") 50 | } 51 | -------------------------------------------------------------------------------- /ginusage/19singlebinary/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: install package build 2 | install: 3 | go install github.com/jessevdk/go-assets-builder 4 | 5 | package: 6 | go-assets-builder html -o assets.go 7 | 8 | build: 9 | go build 10 | -------------------------------------------------------------------------------- /ginusage/19singlebinary/assets.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/jessevdk/go-assets" 7 | ) 8 | 9 | var _Assets3737a75b5254ed1f6d588b40a3449721f9ea86c2 = "\n\n

Hello, {{.Foo}}

\n" 10 | 11 | // Assets returns go-assets FileSystem 12 | var Assets = assets.NewFileSystem(map[string][]string{"/": []string{"html"}, "/html": []string{"index.tmpl"}}, map[string]*assets.File{ 13 | "/": &assets.File{ 14 | Path: "/", 15 | FileMode: 0x800001ed, 16 | Mtime: time.Unix(1580437171, 1580437171291831690), 17 | Data: nil, 18 | }, "/html": &assets.File{ 19 | Path: "/html", 20 | FileMode: 0x800001ed, 21 | Mtime: time.Unix(1580436562, 1580436562948504426), 22 | Data: nil, 23 | }, "/html/index.tmpl": &assets.File{ 24 | Path: "/html/index.tmpl", 25 | FileMode: 0x1a4, 26 | Mtime: time.Unix(1580436562, 1580436562948388946), 27 | Data: []byte(_Assets3737a75b5254ed1f6d588b40a3449721f9ea86c2), 28 | }}, "") 29 | -------------------------------------------------------------------------------- /ginusage/19singlebinary/html/index.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello, {{.Foo}}

4 | -------------------------------------------------------------------------------- /ginusage/19singlebinary/singlebinary.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "html/template" 6 | "io/ioutil" 7 | "log" 8 | "net/http" 9 | "strings" 10 | ) 11 | 12 | func loadTemplate() (*template.Template, error) { 13 | t := template.New("") 14 | for name, file := range Assets.Files { 15 | defer file.Close() 16 | if file.IsDir() || !strings.HasSuffix(name, ".tmpl") { 17 | continue 18 | } 19 | h, err := ioutil.ReadAll(file) 20 | if err != nil { 21 | return nil, err 22 | } 23 | t, err = t.New(name).Parse(string(h)) 24 | if err != nil { 25 | return nil, err 26 | } 27 | } 28 | return t, nil 29 | } 30 | 31 | func main() { 32 | route := gin.Default() 33 | 34 | t, err := loadTemplate() 35 | if err != nil { 36 | log.Fatal("load tempalte: ", err.Error()) 37 | } 38 | 39 | route.SetHTMLTemplate(t) 40 | 41 | route.GET("/", func(c *gin.Context) { 42 | c.HTML(http.StatusOK, "/html/index.tmpl", nil) 43 | }) 44 | route.Run() 45 | } 46 | -------------------------------------------------------------------------------- /ginusage/20http2/assets/app.js: -------------------------------------------------------------------------------- 1 | /* 2 | * app.js 3 | * Copyright (C) 2020 lijiaocn 4 | * 5 | * Distributed under terms of the GPL license. 6 | */ 7 | (function(){ 8 | 'use strict'; 9 | 10 | 11 | })(); 12 | -------------------------------------------------------------------------------- /ginusage/20http2/http2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "html/template" 6 | "log" 7 | "net/http" 8 | ) 9 | 10 | var html = template.Must(template.New("https").Parse(` 11 | 12 | 13 | Https Test 14 | 15 | 16 | 17 |

Welcome {{.user}}

18 | 19 | 20 | `)) 21 | 22 | func main() { 23 | route := gin.Default() 24 | route.Static("/assets", "./assets") 25 | route.SetHTMLTemplate(html) 26 | 27 | route.GET("/", func(c *gin.Context) { 28 | if pusher := c.Writer.Pusher(); pusher != nil { 29 | if err := pusher.Push("/assets/app.js", nil); err != nil { 30 | log.Printf("Failed to push: %s", err.Error()) 31 | } 32 | } 33 | c.HTML(http.StatusOK, "https", gin.H{"user": "guest"}) 34 | }) 35 | route.Run() 36 | } 37 | -------------------------------------------------------------------------------- /ginusage/21cookie/cookie.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gin-gonic/gin" 6 | ) 7 | 8 | func main() { 9 | route := gin.Default() 10 | 11 | route.GET("/cookie", func(c *gin.Context) { 12 | cookie, err := c.Cookie("gin_cookie") 13 | if err != nil { 14 | cookie = "NotSet" 15 | c.SetCookie("gin_cookie", "test", 3600, "/", "localhost", false, true) 16 | } 17 | fmt.Printf("Cookie value: %s\n", cookie) 18 | }) 19 | 20 | route.Run() 21 | } 22 | -------------------------------------------------------------------------------- /ginusage/22test/test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "net/http" 6 | ) 7 | 8 | func setupRoute() *gin.Engine { 9 | route := gin.Default() 10 | 11 | route.GET("/ping", func(c *gin.Context) { 12 | c.String(http.StatusOK, "pong") 13 | }) 14 | return route 15 | } 16 | 17 | func main() { 18 | route := setupRoute() 19 | route.Run() 20 | } 21 | -------------------------------------------------------------------------------- /ginusage/22test/test_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | "net/http/httptest" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestPingRoute(t *testing.T) { 12 | route := setupRoute() 13 | 14 | w := httptest.NewRecorder() 15 | req, _ := http.NewRequest("GET", "/ping", nil) 16 | route.ServeHTTP(w, req) 17 | 18 | assert.Equal(t, 200, w.Code) 19 | assert.Equal(t, "pong", w.Body.String()) 20 | } 21 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module go-code-example 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/coreos/bbolt v1.3.3 // indirect 7 | github.com/coreos/etcd v3.3.13+incompatible // indirect 8 | github.com/coreos/go-semver v0.3.0 // indirect 9 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect 10 | github.com/gin-gonic/autotls v0.0.0-20191129055149-ffaac874b99f // indirect 11 | github.com/gin-gonic/gin v1.5.0 12 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b 13 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect 14 | github.com/google/cadvisor v0.36.0 15 | github.com/gorilla/websocket v1.4.1 // indirect 16 | github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 // indirect 17 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect 18 | github.com/grpc-ecosystem/grpc-gateway v1.12.2 // indirect 19 | github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365 // indirect 20 | github.com/introclass/go-code-example/syntax v0.0.0-20200101151015-2a4ec52492f1 // indirect 21 | github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15 // indirect 22 | github.com/jessevdk/go-assets-builder v0.0.0-20130903091706-b8483521738f // indirect 23 | github.com/jessevdk/go-flags v1.4.0 // indirect 24 | github.com/jinzhu/gorm v1.9.12 25 | github.com/jonboulle/clockwork v0.1.0 // indirect 26 | github.com/lyft/protoc-gen-star v0.4.10 // indirect 27 | github.com/opentracing/opentracing-go v1.1.0 28 | github.com/prometheus/client_golang v1.4.0 // indirect 29 | github.com/sirupsen/logrus v1.4.2 30 | github.com/soheilhy/cmux v0.1.4 // indirect 31 | github.com/spf13/cobra v0.0.5 // indirect 32 | github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc // indirect 33 | github.com/uber/jaeger-client-go v2.22.1+incompatible 34 | github.com/uber/jaeger-lib v2.2.0+incompatible 35 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect 36 | go.etcd.io/etcd v3.3.13+incompatible // indirect 37 | go.uber.org/zap v1.13.0 // indirect 38 | gopkg.in/go-playground/validator.v8 v8.18.2 // indirect 39 | gopkg.in/yaml.v2 v2.2.8 40 | istio.io/gogo-genproto v0.0.0-20190614210408-e88dc8b0e4db // indirect 41 | k8s.io/apimachinery v0.17.3 42 | k8s.io/client-go v0.17.3 43 | k8s.io/utils v0.0.0-20200318093247-d1ab8797c558 // indirect 44 | lijiaocn.com/go/example/mod v1.1.0 // indirect 45 | lijiaocn.com/go/example/mod/v2 v2.0.0 // indirect 46 | ) 47 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= 2 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 5 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= 6 | github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= 7 | github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= 8 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= 9 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 10 | github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 11 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= 12 | github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= 13 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 14 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 15 | github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= 16 | github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= 17 | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= 18 | github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= 19 | github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 20 | github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 21 | github.com/Rican7/retry v0.1.1-0.20160712041035-272ad122d6e5/go.mod h1:FgOROf8P5bebcC1DS0PdOQiqGUridaZvikzUmkFW6gg= 22 | github.com/SeanDolphin/bqschema v0.0.0-20150424181127-f92a08f515e1/go.mod h1:TYInVncsPIZH7kybQoIUNJ4pFX1cUc8LoP9RSOxIs6c= 23 | github.com/Shopify/sarama v1.8.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= 24 | github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= 25 | github.com/abbot/go-http-auth v0.0.0-20140618235127-c0ef4539dfab/go.mod h1:Cz6ARTIzApMJDzh5bRMSUou6UMSp0IEXg9km/ci7TJM= 26 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 27 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 28 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 29 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 30 | github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= 31 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 32 | github.com/aws/aws-sdk-go v1.6.10/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= 33 | github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 34 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 35 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 36 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 37 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 38 | github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= 39 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 40 | github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 41 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 42 | github.com/checkpoint-restore/go-criu v0.0.0-20190109184317-bdb7599cd87b/go.mod h1:TrMrLQfeENAPYPRsJuq3jsqdlRh3lvi6trTZJG8+tho= 43 | github.com/cilium/ebpf v0.0.0-20191113100448-d9fb101ca1fb/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= 44 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 45 | github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= 46 | github.com/containerd/cgroups v0.0.0-20200108155730-918ed86e29cc/go.mod h1:6KyBUkSDshoWUZPkqlFXQzOMWNtlcJ1stduPAd2MRes= 47 | github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= 48 | github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= 49 | github.com/containerd/containerd v1.3.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= 50 | github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= 51 | github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= 52 | github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= 53 | github.com/containerd/fifo v0.0.0-20191213151349-ff969a566b00/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= 54 | github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= 55 | github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= 56 | github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= 57 | github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= 58 | github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= 59 | github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= 60 | github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 61 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 62 | github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= 63 | github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 64 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 65 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 66 | github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= 67 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 68 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 69 | github.com/coreos/go-systemd/v22 v22.0.0-20191111152658-2d78030078ef/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= 70 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= 71 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 72 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 73 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 74 | github.com/cyphar/filepath-securejoin v0.2.2-0.20170720062807-ae69057f2299/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= 75 | github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 76 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 77 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 78 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 79 | github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= 80 | github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= 81 | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= 82 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 83 | github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 84 | github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 85 | github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 86 | github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= 87 | github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 88 | github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 89 | github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 90 | github.com/eapache/go-resiliency v1.0.1-0.20160104191539-b86b1ec0dd42/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= 91 | github.com/eapache/queue v1.0.2/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= 92 | github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 93 | github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 94 | github.com/envoyproxy/go-control-plane v0.8.3 h1:Sqcub1O4SnINoXxNmqbNSeNcZ7O/mkk5jq2Ou6JF7HU= 95 | github.com/envoyproxy/go-control-plane v0.8.3/go.mod h1:EWRTAFN6uuDZIa6KOuUfrOMJ7ySgXZ44rVKiTWjKe34= 96 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 97 | github.com/envoyproxy/go-control-plane v0.9.1 h1:+8frETDtT11P1dMCWySse/d0jMPOKYYF7OZjl7cZLvQ= 98 | github.com/envoyproxy/go-control-plane v0.9.1/go.mod h1:G1fbsNGAFpC1aaERrShZQVdUV2ZuZuv6FCl2v9JNSxQ= 99 | github.com/envoyproxy/protoc-gen-validate v0.0.0-20190405222122-d6164de49109/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 100 | github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= 101 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 102 | github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= 103 | github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= 104 | github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 105 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 106 | github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= 107 | github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 108 | github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= 109 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 110 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 111 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 112 | github.com/gin-gonic/autotls v0.0.0-20191129055149-ffaac874b99f h1:IGnGEhIYwNwaIUZFU2XY+FjlfvDMacuHskkbNlRy/58= 113 | github.com/gin-gonic/autotls v0.0.0-20191129055149-ffaac874b99f/go.mod h1:93AoORd6Jfk8WtgesdalWRZ+IQdbaqc8yVAAhhTjMDQ= 114 | github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc= 115 | github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= 116 | github.com/go-ini/ini v1.9.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 117 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 118 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 119 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 120 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 121 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 122 | github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= 123 | github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= 124 | github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= 125 | github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= 126 | github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= 127 | github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= 128 | github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= 129 | github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= 130 | github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= 131 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 132 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 133 | github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= 134 | github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 135 | github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= 136 | github.com/gogo/googleapis v1.3.1/go.mod h1:d+q1s/xVJxZGKWwC/6UfPIF33J+G1Tq4GYv9Y+Tg/EU= 137 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 138 | github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= 139 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 140 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I= 141 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 142 | github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 143 | github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= 144 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 145 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= 146 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= 147 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= 148 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 149 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 150 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 151 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 152 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= 153 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 154 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 155 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 156 | github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 157 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 158 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 159 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 160 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 161 | github.com/golang/snappy v0.0.0-20150730031844-723cc1e459b8/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 162 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 163 | github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= 164 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 165 | github.com/google/cadvisor v0.36.0 h1:IE0Hng7it0VDtVBkAm+UB+yRtX8WaCLoj10r59P2XW4= 166 | github.com/google/cadvisor v0.36.0/go.mod h1:IOOfMC4Ode4dHj8sItF368GzylPiGpsODxNdxNZsOL8= 167 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 168 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 169 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 170 | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= 171 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 172 | github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= 173 | github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= 174 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 175 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 176 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 177 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 178 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 179 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 180 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k= 181 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 182 | github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= 183 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 184 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 185 | github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= 186 | github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 187 | github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= 188 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 189 | github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= 190 | github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= 191 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= 192 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 193 | github.com/grpc-ecosystem/grpc-gateway v1.12.2 h1:D0EVSTwQoQOyfY35QNSuPJA4jpZRtkoGYWQMB7XNg5o= 194 | github.com/grpc-ecosystem/grpc-gateway v1.12.2/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= 195 | github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 196 | github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= 197 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 198 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 199 | github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= 200 | github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 201 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 202 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 203 | github.com/iancoleman/strcase v0.0.0-20190422225806-e506e3ef7365/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= 204 | github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= 205 | github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 206 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 207 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 208 | github.com/influxdb/influxdb v0.9.6-0.20151125225445-9eab56311373/go.mod h1:GpjLgHRqWhDGlPAg7+Rj6NAYuzPojBM8XLG5Ouvvq+Q= 209 | github.com/introclass/go-code-example v0.0.0-20200101151015-2a4ec52492f1 h1:6EmLIMA82tw14kucy4ao+EgsQGZnBD1a3+RG+KHt1ME= 210 | github.com/introclass/go-code-example/syntax v0.0.0-20200101151015-2a4ec52492f1 h1:RqzIOlFFvNLey/mnGKkgdX9+UcMqn1mHgzEdy79WrK0= 211 | github.com/introclass/go-code-example/syntax v0.0.0-20200101151015-2a4ec52492f1/go.mod h1:h7PMd4TWRXY2MTClc0JFYy2oeBfA3NL+gpCUd+ICCYA= 212 | github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15 h1:cW/amwGEJK5MSKntPXRjX4dxs/nGxGT8gXKIsKFmHGc= 213 | github.com/jessevdk/go-assets v0.0.0-20160921144138-4f4301a06e15/go.mod h1:Fdm/oWRW+CH8PRbLntksCNtmcCBximKPkVQYvmMl80k= 214 | github.com/jessevdk/go-assets-builder v0.0.0-20130903091706-b8483521738f h1:K2zqtTU3T3ZX/vVeFtJ1OoxEm+gsLhu3zQ34tKgOAyk= 215 | github.com/jessevdk/go-assets-builder v0.0.0-20130903091706-b8483521738f/go.mod h1:GjkD6wGIxVEccQ4pa27Ebe00zAi1EEpAcL6rL0ADvwU= 216 | github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= 217 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 218 | github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q= 219 | github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= 220 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 221 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 222 | github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 223 | github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 224 | github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= 225 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 226 | github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 227 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 228 | github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= 229 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 230 | github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 231 | github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= 232 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 233 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 234 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 235 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 236 | github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= 237 | github.com/kevinburke/go-bindata v3.17.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= 238 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 239 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 240 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 241 | github.com/klauspost/crc32 v0.0.0-20151223135126-a3b15ae34567/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= 242 | github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= 243 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 244 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 245 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 246 | github.com/kr/pretty v0.0.0-20140723054909-088c856450c0/go.mod h1:Bvhd+E3laJ0AVkG0c9rmtZcnhV0HQ3+c3YxxqTvc/gA= 247 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 248 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 249 | github.com/kr/text v0.0.0-20130911015532-6807e777504f/go.mod h1:sjUstKUATFIcff4qlB53Kml0wQPtJVc/3fWrmuUmcfA= 250 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 251 | github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= 252 | github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= 253 | github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4= 254 | github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 255 | github.com/lyft/protoc-gen-star v0.4.10/go.mod h1:mE8fbna26u7aEA2QCVvvfBU/ZrPgocG1206xAFPcs94= 256 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 257 | github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 258 | github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= 259 | github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 260 | github.com/mattn/go-shellwords v1.0.4-0.20180201004752-39dbbfa24bbc/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= 261 | github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw= 262 | github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 263 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 264 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 265 | github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= 266 | github.com/mesos/mesos-go v0.0.7-0.20180413204204-29de6ff97b48/go.mod h1:kPYCMQ9gsOXVAle1OsoY4I1+9kPu8GHkf88aV59fDr4= 267 | github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY= 268 | github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= 269 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 270 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 271 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 272 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 273 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 274 | github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 275 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 276 | github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= 277 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 278 | github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= 279 | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 280 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 281 | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 282 | github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 283 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 284 | github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 285 | github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 286 | github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 287 | github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 288 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 289 | github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 290 | github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 291 | github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= 292 | github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= 293 | github.com/opencontainers/runc v1.0.0-rc10/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= 294 | github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= 295 | github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= 296 | github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= 297 | github.com/opencontainers/selinux v1.3.3/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= 298 | github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= 299 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 300 | github.com/pborman/uuid v0.0.0-20150824212802-cccd189d45f7/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= 301 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 302 | github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= 303 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 304 | github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 305 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 306 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 307 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 308 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 309 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 310 | github.com/pquerna/ffjson v0.0.0-20171002144729-d49c2bc1aa13/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= 311 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 312 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 313 | github.com/prometheus/client_golang v1.4.0 h1:YVIb/fVcOTMSqtqZWSKnHpSLBxu8DKgxq8z6RuBZwqI= 314 | github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= 315 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 316 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 317 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 318 | github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= 319 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 320 | github.com/prometheus/common v0.0.0-20170220103846-49fee292b27b/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 321 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 322 | github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= 323 | github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= 324 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 325 | github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 326 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 327 | github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= 328 | github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= 329 | github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 330 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 331 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 332 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 333 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 334 | github.com/seccomp/libseccomp-golang v0.0.0-20150813023252-1b506fc7c24e/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= 335 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 336 | github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= 337 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 338 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 339 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 340 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 341 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 342 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 343 | github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= 344 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 345 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 346 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 347 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 348 | github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 349 | github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= 350 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 351 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 352 | github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 353 | github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 354 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 355 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 356 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 357 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 358 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 359 | github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= 360 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 361 | github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 362 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 363 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 364 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 365 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 366 | github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= 367 | github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= 368 | github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc h1:yUaosFVTJwnltaHbSNC3i82I92quFs+OFPRl8kNMVwo= 369 | github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 370 | github.com/uber/jaeger-client-go v2.22.1+incompatible h1:NHcubEkVbahf9t3p75TOCR83gdUHXjRJvjoBh1yACsM= 371 | github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= 372 | github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= 373 | github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= 374 | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= 375 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 376 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 377 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 378 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 379 | github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= 380 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 381 | github.com/vishvananda/netlink v0.0.0-20150820014904-1e2e08e8a2dc/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= 382 | github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= 383 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= 384 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= 385 | github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= 386 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= 387 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 388 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 389 | go.etcd.io/etcd v3.3.13+incompatible h1:jCejD5EMnlGxFvcGRyEV4VGlENZc7oPQX6o0t7n3xbw= 390 | go.etcd.io/etcd v3.3.13+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI= 391 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 392 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 393 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 394 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 395 | go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= 396 | go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 397 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 398 | go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc= 399 | go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= 400 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= 401 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 402 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 403 | go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= 404 | go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= 405 | golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 406 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 407 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 408 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 409 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= 410 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 411 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 412 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk= 413 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 414 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 415 | golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM= 416 | golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 417 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 418 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 419 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 420 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 421 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 422 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= 423 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 424 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 425 | golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 426 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 427 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 428 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 429 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 430 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 431 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 432 | golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= 433 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 434 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 435 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 436 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= 437 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 438 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 439 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 440 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 441 | golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs= 442 | golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 443 | golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI= 444 | golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 445 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= 446 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 447 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= 448 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 449 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 450 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= 451 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 452 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 453 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 454 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 455 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 456 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 457 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= 458 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 459 | golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 460 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 461 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 462 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 463 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 464 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 465 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 466 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 467 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 468 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 469 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 470 | golang.org/x/sys v0.0.0-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 471 | golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 472 | golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 473 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= 474 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 475 | golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 476 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 477 | golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 478 | golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 479 | golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 480 | golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 481 | golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 482 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= 483 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 484 | golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 485 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 486 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 487 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 488 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 489 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 490 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 491 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 492 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= 493 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 494 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 495 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 496 | golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 497 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 498 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 499 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 500 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 501 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 502 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 503 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 504 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 505 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 506 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= 507 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 508 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 509 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 510 | google.golang.org/api v0.0.0-20150730141719-0c2979aeaa5b/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 511 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 512 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 513 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 514 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 515 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 516 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= 517 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 518 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 519 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 520 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 521 | google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= 522 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= 523 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 524 | google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC1n2AJGVhrwiEjOi35+jxtIuZpTMo= 525 | google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 526 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 527 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 528 | google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM= 529 | google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 530 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 531 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 532 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 533 | google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= 534 | google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= 535 | google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= 536 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 537 | gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= 538 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 539 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 540 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 541 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 542 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 543 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 544 | gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= 545 | gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= 546 | gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= 547 | gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= 548 | gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc= 549 | gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= 550 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 551 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 552 | gopkg.in/olivere/elastic.v2 v2.0.12/go.mod h1:CTVyl1gckiFw1aLZYxC00g3f9jnHmhoOKcWF7W3c6n4= 553 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 554 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 555 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 556 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 557 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 558 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 559 | gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= 560 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 561 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 562 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 563 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 564 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 565 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 566 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 567 | honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= 568 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 569 | istio.io/gogo-genproto v0.0.0-20190614210408-e88dc8b0e4db/go.mod h1:eIDJ6jNk/IeJz6ODSksHl5Aiczy5JUq6vFhJWI5OtiI= 570 | k8s.io/api v0.17.2 h1:NF1UFXcKN7/OOv1uxdRz3qfra8AHsPav5M93hlV9+Dc= 571 | k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4= 572 | k8s.io/api v0.17.3 h1:XAm3PZp3wnEdzekNkcmj/9Y1zdmQYJ1I4GKSBBZ8aG0= 573 | k8s.io/api v0.17.3/go.mod h1:YZ0OTkuw7ipbe305fMpIdf3GLXZKRigjtZaV5gzC2J0= 574 | k8s.io/apimachinery v0.17.2 h1:hwDQQFbdRlpnnsR64Asdi55GyCaIP/3WQpMmbNBeWr4= 575 | k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= 576 | k8s.io/apimachinery v0.17.3 h1:f+uZV6rm4/tHE7xXgLyToprg6xWairaClGVkm2t8omg= 577 | k8s.io/apimachinery v0.17.3/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g= 578 | k8s.io/client-go v0.17.3 h1:deUna1Ksx05XeESH6XGCyONNFfiQmDdqeqUvicvP6nU= 579 | k8s.io/client-go v0.17.3/go.mod h1:cLXlTMtWHkuK4tD360KpWz2gG2KtdWEr/OT02i3emRQ= 580 | k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o= 581 | k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= 582 | k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 583 | k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 584 | k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 585 | k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= 586 | k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= 587 | k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= 588 | k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= 589 | k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 590 | k8s.io/utils v0.0.0-20200122174043-1e243dd1a584/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 591 | k8s.io/utils v0.0.0-20200318093247-d1ab8797c558 h1:yaUqfD7/dWM081lhpYGB+Wi4awn61TY7WcAc6usJMR8= 592 | k8s.io/utils v0.0.0-20200318093247-d1ab8797c558/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 593 | lijiaocn.com/go/example/mod v1.1.0 h1:gcu9xmhULUJA4dwT12ncF6nwvj57zc6jgtLKmFb+dw8= 594 | lijiaocn.com/go/example/mod v1.1.0/go.mod h1:QsFfBJ5+S3zFRJnrumIDBiyxS9eJXv7q+9C0WPKNyYk= 595 | lijiaocn.com/go/example/mod/v2 v2.0.0 h1:SXPU6kTyEkkAyGamNnOoM0AbgFGhQnipnI0blP6SfAs= 596 | lijiaocn.com/go/example/mod/v2 v2.0.0/go.mod h1:+7r7UGmiae0qKH6YrpuTtvDecI2besUtZ6YbWwm/vd8= 597 | sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= 598 | sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= 599 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 600 | -------------------------------------------------------------------------------- /gormusage/01connect/connect.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/golang/glog" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/mssql" 7 | _ "github.com/jinzhu/gorm/dialects/mysql" 8 | _ "github.com/jinzhu/gorm/dialects/postgres" 9 | _ "github.com/jinzhu/gorm/dialects/sqlite" 10 | ) 11 | 12 | func main() { 13 | // 准备数据库 14 | // create database gormdb; 15 | // create user 'gorm'@'%' identified by 'passwd123'; 16 | // alter user 'gorm'@'%' identified with mysql_native_password by 'password123'; 17 | // grant all on gormdb.* to 'gorm'@'%'; 18 | // flush privileges; 19 | 20 | //mysql, err := gorm.Open("mysql", "user:password@(localhost)/dbname?charset=utf8&parseTime=True&loc=Local") 21 | mysql, err := gorm.Open("mysql", "gorm:passwd123@(localhost)/gormdb?charset=utf8&parseTime=True&loc=Local") 22 | if err != nil { 23 | glog.Fatal("mysql: ", err.Error()) 24 | } 25 | defer mysql.Close() 26 | 27 | sqlite, err := gorm.Open("sqlite3", "/tmp/gorm.db") 28 | if err != nil { 29 | glog.Fatal("sqlite3: ", err.Error()) 30 | } 31 | defer sqlite.Close() 32 | 33 | // 准备数据库 34 | // create user gorm with password 'password123'; 35 | // create database gormdb; 36 | // grant all on database gormdb to gorm; 37 | // 38 | // 在 pg_hba.conf 中添加配置: 39 | // host gormdb gorm 0.0.0.0/0 password 40 | // hostssl gormdb gorm 0.0.0.0/0 password 41 | // 42 | // 命令行登陆 43 | // psql -U gorm gormdb -h 127.0.0.1 -p 5432 44 | 45 | //postgres, err := gorm.Open("postgres", "host=127.0.0.1 port=5432 user=gorm dbname=gormdb password=password123 sslmode=disable") 46 | postgres, err := gorm.Open("postgres", "postgres://gorm:password123@localhost/gormdb?sslmode=disable") 47 | if err != nil { 48 | glog.Fatal("postgres: ", err.Error()) 49 | } 50 | defer postgres.Close() 51 | 52 | //mssql, err := gorm.Open("mssql", "sqlserver://username:password@localhost:1433?database=dbname") 53 | //if err != nil { 54 | // glog.Fatal("mssql: ", err.Error()) 55 | //} 56 | //defer mssql.Close() 57 | 58 | } 59 | -------------------------------------------------------------------------------- /gormusage/02model/models.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "go-code-example/gormusage/common" 5 | 6 | "github.com/golang/glog" 7 | "github.com/jinzhu/gorm" 8 | _ "github.com/jinzhu/gorm/dialects/mysql" 9 | ) 10 | 11 | func main() { 12 | db, err := gorm.Open("mysql", "gorm:password123@(localhost)/gormdb?charset=utf8&parseTime=True&loc=Local") 13 | if err != nil { 14 | glog.Fatal(err.Error()) 15 | } 16 | defer db.Close() 17 | 18 | // 表名默认是 struct 名称的复数形式,使用单数形式: 19 | db.SingularTable(true) 20 | 21 | // 自定义表名命名规则 22 | gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string { 23 | return "prefix_" + defaultTableName 24 | } 25 | 26 | if !db.HasTable(&common.User{}) { 27 | db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&common.User{}) 28 | } 29 | 30 | if !db.HasTable(&common.TableStudent{}) { 31 | db.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&common.TableStudent{}) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gormusage/03crud/crud.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "go-code-example/gormusage/common" 6 | 7 | "github.com/golang/glog" 8 | "github.com/jinzhu/gorm" 9 | _ "github.com/jinzhu/gorm/dialects/mysql" 10 | ) 11 | 12 | func create(db *gorm.DB) error { 13 | var num string = "00001" 14 | user := common.User{ 15 | Name: "user1", 16 | MemberNumber: &num, 17 | Role: "normal", 18 | } 19 | return db.Save(&user).Error 20 | } 21 | 22 | func create2(db *gorm.DB) error { 23 | student := &common.Student{ 24 | Name: "xiao a", 25 | } 26 | return db.Save(student).Error 27 | } 28 | 29 | func read(db *gorm.DB) (*common.User, error) { 30 | var user common.User 31 | var num string = "00001" 32 | dberr := db.Where(&common.User{MemberNumber: &num}).First(&user).Error 33 | if dberr != nil { 34 | return nil, dberr 35 | } 36 | return &user, nil 37 | } 38 | 39 | func read2(db *gorm.DB) (*common.Student, error) { 40 | var student = &common.Student{ 41 | Name: "xiao a", 42 | } 43 | dberr := db.Where(student).First(student).Error 44 | if dberr != nil { 45 | return nil, dberr 46 | } 47 | return student, nil 48 | } 49 | 50 | func update(db *gorm.DB) error { 51 | var num string = "00002" 52 | user := common.User{ 53 | Name: "user1", 54 | MemberNumber: &num, 55 | Role: "admin", 56 | } 57 | var oriUser common.User 58 | dberr := db.Where(&common.User{MemberNumber: user.MemberNumber}).First(&oriUser).Error 59 | if dberr != nil { 60 | return dberr 61 | } 62 | user.ID = 100 63 | return db.Save(&user).Error 64 | } 65 | 66 | func delete(db *gorm.DB) error { 67 | var num string = "00001" 68 | user := common.User{ 69 | MemberNumber: &num, 70 | } 71 | return db.Delete(&user).Error 72 | } 73 | 74 | func main() { 75 | db, err := gorm.Open("mysql", "gorm:password123@(localhost)/gormdb?charset=utf8&parseTime=True&loc=Local") 76 | if err != nil { 77 | glog.Fatal(err.Error()) 78 | } 79 | defer db.Close() 80 | 81 | //Create 82 | if err := create(db); err != nil { 83 | glog.Error(err.Error()) 84 | } 85 | 86 | if err := create2(db); err != nil { 87 | glog.Error(err.Error()) 88 | } 89 | 90 | //Read 91 | if user, err := read(db); err != nil { 92 | glog.Error(err.Error()) 93 | } else { 94 | fmt.Printf("read user info: %v\n", user) 95 | } 96 | 97 | if student, err := read2(db); err != nil { 98 | glog.Error(err.Error()) 99 | } else { 100 | fmt.Printf("read user info: %v\n", student) 101 | } 102 | 103 | //Update 104 | update(db) 105 | if user, err := read(db); err != nil { 106 | glog.Error(err.Error()) 107 | } else { 108 | fmt.Printf("read user info: %v\n", user) 109 | } 110 | 111 | //Delete 112 | delete(db) 113 | } 114 | -------------------------------------------------------------------------------- /gormusage/common/student.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/jinzhu/gorm" 7 | ) 8 | 9 | type TableStudent struct { 10 | Student 11 | Extra 12 | } 13 | 14 | type Student struct { 15 | ID uint `gorm:"primary_key"` 16 | Name string `gorm:"type:varchar(100)"` 17 | } 18 | 19 | type Extra struct { 20 | CreatedAt time.Time 21 | UpdatedAt time.Time 22 | DeletedAt *time.Time `sql:"index"` 23 | } 24 | 25 | func (TableStudent) TableName() string { 26 | return "Students" 27 | } 28 | 29 | func (self *Student) Read(db *gorm.DB) error { 30 | return db.Where(self).First(self).Error 31 | } 32 | 33 | func (self *Student) Create(db *gorm.DB) error { 34 | return db.Create(self).Error 35 | } 36 | 37 | func (self *Student) Update(db *gorm.DB) error { 38 | return db.Save(self).Error 39 | } 40 | -------------------------------------------------------------------------------- /gormusage/common/user.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "database/sql" 5 | "time" 6 | 7 | "github.com/jinzhu/gorm" 8 | ) 9 | 10 | /* 11 | Column 指定列名 12 | Type 指定列数据类型 13 | Size 指定列大小, 默认值255 14 | PRIMARY_KEY 将列指定为主键 15 | UNIQUE 将列指定为唯一 16 | DEFAULT 指定列默认值 17 | PRECISION 指定列精度 18 | NOT NULL 将列指定为非 NULL 19 | AUTO_INCREMENT 指定列是否为自增类型 20 | INDEX 创建具有或不带名称的索引, 如果多个索引同名则创建复合索引 21 | UNIQUE_INDEX 和 INDEX 类似,只不过创建的是唯一索引 22 | EMBEDDED 将结构设置为嵌入 23 | EMBEDDED_PREFIX 设置嵌入结构的前缀 24 | - 忽略此字段 25 | 26 | 用于表关联相关的 struct tag 27 | 28 | MANY2MANY 指定连接表 29 | FOREIGNKEY 设置外键 30 | ASSOCIATION_FOREIGNKEY 设置关联外键 31 | POLYMORPHIC 指定多态类型 32 | POLYMORPHIC_VALUE 指定多态值 33 | JOINTABLE_FOREIGNKEY 指定连接表的外键 34 | ASSOCIATION_JOINTABLE_FOREIGNKEY 指定连接表的关联外键 35 | SAVE_ASSOCIATIONS 是否自动完成 save 的相关操作 36 | ASSOCIATION_AUTOUPDATE 是否自动完成 update 的相关操作 37 | ASSOCIATION_AUTOCREATE 是否自动完成 create 的相关操作 38 | ASSOCIATION_SAVE_REFERENCE 是否自动完成引用的 save 的相关操作 39 | PRELOAD 是否自动完成预加载的相关操作 40 | */ 41 | 42 | type User struct { 43 | gorm.Model //gorm 内置的惯例字段,可用可不用 44 | // CreatedAt 自动设置为记录的首次时间:db.Create(&user) 45 | // 如果更新用 Update 方法: db.Model(&user).Update("CreatedAt", time.Now()) 46 | // UpdatedAt 在记录变更时自动更新:db.Save(&user) 47 | // DeletedAt 在删除时设置为删除时间(如果有 DeleteAt 字段,默认使用软删除) 48 | Name string 49 | Ages sql.NullInt32 50 | Birthday *time.Time 51 | Email string `gorm:"type:varchar(100);unique_index"` //类型,唯一索引 52 | Role string `gorm:"size:255"` 53 | MemberNumber *string `gorm:"unique;not null"` 54 | Num int `gorm:"AUTO_INCREMENT"` 55 | Address string `gorm:"index:addr"` 56 | IgnoreMe int `gorm:"-"` //忽略字段 57 | } 58 | 59 | // 可以用此方法修改表名,也可以在创建表的时候修改 60 | func (User) TableName() string { 61 | return "users" 62 | } 63 | 64 | /* 根据情况,返回不同的表名 65 | func (u User) TableName() string { 66 | if u.Role == "admin" { 67 | return "admin_users" 68 | } else { 69 | return "users" 70 | } 71 | } 72 | */ 73 | 74 | func (u *User) Read(db *gorm.DB) error { 75 | return db.Where(u).First(u).Error 76 | } 77 | 78 | func (u *User) Create(db *gorm.DB) error { 79 | return db.Create(u).Error 80 | } 81 | 82 | func (u *User) Update(db *gorm.DB) error { 83 | return db.Save(u).Error 84 | } 85 | -------------------------------------------------------------------------------- /k8sclient/beartoken/main.go: -------------------------------------------------------------------------------- 1 | //create: 2017/11/15 16:05:17 change: 2017/11/17 09:58:07 author:lijiao 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | 7 | "k8s.io/client-go/kubernetes" 8 | "k8s.io/client-go/rest" 9 | ) 10 | 11 | func main() { 12 | config := rest.Config{ 13 | Host: "https://10.39.0.105:6443", 14 | APIPath: "/", 15 | BearerToken: "bf8cb8725efab8c4", 16 | TLSClientConfig: rest.TLSClientConfig{Insecure: true}, 17 | } 18 | clientset, err := kubernetes.NewForConfig(&config) 19 | if err != nil { 20 | panic(err.Error()) 21 | } 22 | 23 | pods, err := clientset.CoreV1().Pods("lijiaocn").List(v1.ListOptions{}) 24 | if err != nil { 25 | panic(err.Error()) 26 | } 27 | 28 | fmt.Printf("There are %d pods in the cluster.\n", len(pods.Items)) 29 | } 30 | -------------------------------------------------------------------------------- /k8sclient/clientset/clientset.go: -------------------------------------------------------------------------------- 1 | //create: 2017/11/15 16:05:17 change: 2017/11/17 09:58:07 author:lijiao 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | 9 | "github.com/golang/glog" 10 | 11 | "k8s.io/client-go/tools/clientcmd" 12 | 13 | "k8s.io/apimachinery/pkg/apis/meta/v1" 14 | "k8s.io/client-go/kubernetes" 15 | ) 16 | 17 | func main() { 18 | home, err := os.UserHomeDir() 19 | if err != nil { 20 | glog.Fatal(err.Error()) 21 | } 22 | 23 | file, err := filepath.Abs(home + "/.kube/config") 24 | if err != nil { 25 | glog.Fatal(err.Error()) 26 | } 27 | 28 | config, err := clientcmd.BuildConfigFromFlags("", file) 29 | if err != nil { 30 | glog.Fatal(err.Error()) 31 | return 32 | } 33 | 34 | clientset, err := kubernetes.NewForConfig(config) 35 | if err != nil { 36 | glog.Fatal(err.Error()) 37 | return 38 | } 39 | 40 | if clientset == nil { 41 | glog.Fatal("clientset is nil") 42 | return 43 | } 44 | 45 | namespace := "kube-system" 46 | pods, err := clientset.CoreV1().Pods(namespace).List(v1.ListOptions{}) 47 | if err != nil { 48 | glog.Fatal(err.Error()) 49 | return 50 | } 51 | 52 | if pods == nil { 53 | fmt.Printf("There are no pods in namespace %s.\n", namespace) 54 | } else { 55 | fmt.Printf("There are %d pods in namespace %s.\n", len(pods.Items), namespace) 56 | } 57 | 58 | ns, err := clientset.CoreV1().Namespaces().List(v1.ListOptions{}) 59 | if err != nil { 60 | glog.Fatal(err.Error()) 61 | return 62 | } 63 | 64 | if ns == nil { 65 | fmt.Printf("There are no namespaces.\n") 66 | } else { 67 | fmt.Printf("There are %d namespaces.\n", len(ns.Items)) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /k8sclient/incluster/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.9.5 2 | 3 | WORKDIR /root 4 | ADD ./incluster /root 5 | 6 | CMD ["./incluster"] 7 | -------------------------------------------------------------------------------- /k8sclient/incluster/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile 3 | # lijiaocn, 2020-03-19 23:37 4 | # 5 | 6 | all: 7 | @echo "Makefile needs your attention" 8 | GOOS=linux go build 9 | docker build -t incluster . 10 | docker tag incluster:latest lijiaocn/incluster:latest 11 | docker push lijiaocn/incluster:latest 12 | 13 | # vim:ft=make 14 | # 15 | -------------------------------------------------------------------------------- /k8sclient/incluster/deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | name: incluster 6 | namespace: monitoring 7 | spec: 8 | progressDeadlineSeconds: 600 9 | replicas: 1 10 | revisionHistoryLimit: 10 11 | selector: 12 | matchLabels: 13 | app: incluster 14 | strategy: 15 | rollingUpdate: 16 | maxSurge: 25% 17 | maxUnavailable: 25% 18 | type: RollingUpdate 19 | template: 20 | metadata: 21 | creationTimestamp: null 22 | labels: 23 | app: incluster 24 | spec: 25 | containers: 26 | - image: lijiaocn/incluster:latest 27 | imagePullPolicy: Always 28 | name: incluster 29 | resources: {} 30 | terminationMessagePath: /dev/termination-log 31 | terminationMessagePolicy: File 32 | dnsPolicy: ClusterFirst 33 | restartPolicy: Always 34 | schedulerName: default-scheduler 35 | serviceAccount: monitoring 36 | serviceAccountName: monitoring 37 | terminationGracePeriodSeconds: 30 38 | -------------------------------------------------------------------------------- /k8sclient/incluster/incluster.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/golang/glog" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | "k8s.io/client-go/kubernetes" 10 | "k8s.io/client-go/rest" 11 | ) 12 | 13 | func main() { 14 | config, err := rest.InClusterConfig() 15 | if err != nil { 16 | glog.Fatal(err) 17 | } 18 | 19 | clientset, err := kubernetes.NewForConfig(config) 20 | if err != nil { 21 | glog.Fatal(err.Error()) 22 | return 23 | } 24 | spaceList, err := clientset.CoreV1().Namespaces().List(metav1.ListOptions{}) 25 | if err != nil { 26 | glog.Fatal(err.Error()) 27 | } 28 | for _, v := range spaceList.Items { 29 | fmt.Println("namesapce: %s\n", v.Name) 30 | } 31 | time.Sleep(1000 * time.Second) 32 | } 33 | -------------------------------------------------------------------------------- /k8sclient/informer/informer.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 lijiaocn wechat: lijiaocn 2 | // 3 | // Distributed under terms of the GPL license. 4 | 5 | package main 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | "os" 11 | "os/signal" 12 | "path/filepath" 13 | "syscall" 14 | "time" 15 | 16 | "k8s.io/apimachinery/pkg/fields" 17 | 18 | "k8s.io/client-go/tools/cache" 19 | 20 | "github.com/golang/glog" 21 | core_v1 "k8s.io/api/core/v1" 22 | "k8s.io/client-go/kubernetes" 23 | "k8s.io/client-go/rest" 24 | "k8s.io/client-go/tools/clientcmd" 25 | ) 26 | 27 | func printEndpoint(ep *core_v1.Endpoints) { 28 | fmt.Printf("%s in %s:\n", ep.Name, ep.Namespace) 29 | for i, sub := range ep.Subsets { 30 | fmt.Printf("\t%d: %s\n", i, sub.String()) 31 | } 32 | } 33 | 34 | // get restClient from clientset 35 | func GetCoreRestClient(config *rest.Config) (rest.Interface, error) { 36 | 37 | clientset, err := kubernetes.NewForConfig(config) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | if clientset == nil { 43 | return nil, errors.New("clientset is nil") 44 | } 45 | 46 | restClient := clientset.CoreV1().RESTClient() 47 | if restClient == nil { 48 | return nil, errors.New("restclient is nil") 49 | } 50 | 51 | return restClient, nil 52 | } 53 | 54 | func main() { 55 | home, err := os.UserHomeDir() 56 | if err != nil { 57 | glog.Fatal(err.Error()) 58 | } 59 | 60 | file, err := filepath.Abs(home + "/.kube/config") 61 | if err != nil { 62 | glog.Fatal(err.Error()) 63 | } 64 | 65 | config, err := clientcmd.BuildConfigFromFlags("", file) 66 | if err != nil { 67 | glog.Fatal(err.Error()) 68 | return 69 | } 70 | 71 | restClient, err := GetCoreRestClient(config) 72 | if err != nil { 73 | glog.Fatal(err.Error()) 74 | return 75 | } 76 | 77 | labels := make(map[string]string) 78 | selector := fields.SelectorFromSet(labels) 79 | listwatch := cache.NewListWatchFromClient(restClient, "endpoints", "", selector) 80 | 81 | handler := cache.ResourceEventHandlerFuncs{ 82 | AddFunc: func(obj interface{}) { 83 | fmt.Printf("Add endpoint:\n") 84 | if ep, ok := obj.(*core_v1.Endpoints); !ok { 85 | fmt.Printf("not endpoints\n") 86 | } else { 87 | printEndpoint(ep) 88 | } 89 | }, 90 | UpdateFunc: func(oldObj, newObj interface{}) { 91 | fmt.Printf("Update endpoint:\n") 92 | if epOld, ok := oldObj.(*core_v1.Endpoints); !ok { 93 | fmt.Printf("not endpoints\n") 94 | } else { 95 | printEndpoint(epOld) 96 | } 97 | 98 | if epNew, ok := newObj.(*core_v1.Endpoints); !ok { 99 | fmt.Printf("not endpoints\n") 100 | } else { 101 | printEndpoint(epNew) 102 | } 103 | }, 104 | DeleteFunc: func(obj interface{}) { 105 | fmt.Printf("Delete endpoint:\n") 106 | if ep, ok := obj.(*core_v1.Endpoints); !ok { 107 | fmt.Printf("not endpoint") 108 | } else { 109 | printEndpoint(ep) 110 | } 111 | }, 112 | } 113 | 114 | stop := make(chan struct{}) 115 | store, controller := cache.NewInformer(listwatch, &core_v1.Endpoints{}, 0*time.Second, handler) 116 | go controller.Run(stop) 117 | 118 | time.Sleep(5 * time.Second) 119 | fmt.Printf("keys\n") 120 | for _, key := range store.ListKeys() { 121 | fmt.Printf("key: %s\n", key) 122 | } 123 | 124 | //Set signal 125 | signalChan := make(chan os.Signal) 126 | signal.Notify(signalChan, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGUSR1) 127 | 128 | for { 129 | select { 130 | case s := <-signalChan: 131 | switch s { 132 | case syscall.SIGQUIT: 133 | fallthrough 134 | case syscall.SIGKILL: 135 | fallthrough 136 | case syscall.SIGTERM: 137 | var obj struct{} 138 | stop <- obj 139 | case syscall.SIGUSR1: 140 | for i, v := range store.ListKeys() { 141 | fmt.Printf("%d : %s\n", i, v) 142 | } 143 | default: 144 | continue 145 | } 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /k8sclient/podinfo/podinfo.go: -------------------------------------------------------------------------------- 1 | //create: 2017/11/15 16:05:17 change: 2017/11/17 09:58:07 author:lijiao 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | 9 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | 11 | "github.com/golang/glog" 12 | 13 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 14 | "k8s.io/client-go/kubernetes" 15 | "k8s.io/client-go/tools/clientcmd" 16 | ) 17 | 18 | func main() { 19 | home, err := os.UserHomeDir() 20 | if err != nil { 21 | glog.Fatal(err.Error()) 22 | } 23 | 24 | file, err := filepath.Abs(home + "/.kube/config") 25 | if err != nil { 26 | glog.Fatal(err.Error()) 27 | } 28 | 29 | config, err := clientcmd.BuildConfigFromFlags("", file) 30 | if err != nil { 31 | glog.Fatal(err.Error()) 32 | return 33 | } 34 | 35 | clientset, err := kubernetes.NewForConfig(config) 36 | if err != nil { 37 | glog.Fatal(err.Error()) 38 | return 39 | } 40 | 41 | if clientset == nil { 42 | glog.Fatal("clientset is nil") 43 | return 44 | } 45 | 46 | namespace := "kube-system" 47 | pods, err := clientset.CoreV1().Pods(namespace).List(v1.ListOptions{}) 48 | if err != nil { 49 | glog.Fatal(err.Error()) 50 | return 51 | } 52 | 53 | if pods == nil { 54 | fmt.Printf("There are no pods in namespace %s.\n", namespace) 55 | } else { 56 | fmt.Printf("There are %d pods in namespace %s.\n", len(pods.Items), namespace) 57 | } 58 | 59 | ns, err := clientset.CoreV1().Namespaces().List(v1.ListOptions{}) 60 | if err != nil { 61 | glog.Fatal(err.Error()) 62 | return 63 | } 64 | 65 | if ns == nil { 66 | fmt.Printf("There are no namespaces.\n") 67 | } else { 68 | fmt.Printf("There are %d namespaces.\n", len(ns.Items)) 69 | } 70 | 71 | namespace = "devops-selftest-1" 72 | pod, err := clientset.CoreV1().Pods(namespace).Get("nginx-996b77c56-mmws6", metav1.GetOptions{}) 73 | if err != nil { 74 | fmt.Printf("%s\n", err.Error()) 75 | } 76 | for i, v := range pod.Spec.Containers { 77 | fmt.Printf("%d: %s\n", i, v.Name) 78 | for ii, vv := range v.Resources.Requests { 79 | fmt.Printf("\trequest: %s %.3f\n", ii, float64(vv.MilliValue())/1000) 80 | } 81 | for ii, vv := range v.Resources.Limits { 82 | fmt.Printf("\tlimit: %s %d\n", ii, vv.Value()) 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /k8sclient/restclient/restclient.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2019 lijiaocn wechat: lijiaocn 2 | // 3 | // Distributed under terms of the GPL license. 4 | 5 | package main 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | "os" 11 | "path/filepath" 12 | 13 | "k8s.io/apimachinery/pkg/runtime/serializer" 14 | "k8s.io/client-go/kubernetes/scheme" 15 | 16 | "github.com/golang/glog" 17 | core_v1 "k8s.io/api/core/v1" 18 | "k8s.io/client-go/kubernetes" 19 | "k8s.io/client-go/rest" 20 | "k8s.io/client-go/tools/clientcmd" 21 | ) 22 | 23 | // create restClient from config 24 | func CreateCoreRestClient(config *rest.Config) (*rest.RESTClient, error) { 25 | 26 | config.ContentConfig.GroupVersion = &core_v1.SchemeGroupVersion 27 | config.ContentConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} 28 | config.APIPath = "/api" 29 | 30 | restClient, err := rest.RESTClientFor(config) 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | if restClient == nil { 36 | return nil, errors.New("restclient1 is nil") 37 | } 38 | 39 | return restClient, nil 40 | } 41 | 42 | // get restClient from clientset 43 | func GetCoreRestClient(config *rest.Config) (rest.Interface, error) { 44 | 45 | clientset, err := kubernetes.NewForConfig(config) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | if clientset == nil { 51 | return nil, errors.New("clientset is nil") 52 | } 53 | 54 | restClient := clientset.CoreV1().RESTClient() 55 | if restClient == nil { 56 | return nil, errors.New("restclient is nil") 57 | } 58 | 59 | return restClient, nil 60 | } 61 | 62 | func main() { 63 | 64 | home, err := os.UserHomeDir() 65 | if err != nil { 66 | glog.Fatal(err.Error()) 67 | } 68 | 69 | file, err := filepath.Abs(home + "/.kube/config") 70 | if err != nil { 71 | glog.Fatal(err.Error()) 72 | } 73 | 74 | config, err := clientcmd.BuildConfigFromFlags("", file) 75 | if err != nil { 76 | glog.Fatal(err.Error()) 77 | return 78 | } 79 | 80 | //方法1: 直接创建 restClient 81 | restClient, err := CreateCoreRestClient(config) 82 | if err != nil { 83 | glog.Fatal(err.Error()) 84 | return 85 | } 86 | 87 | // /// 88 | // GET https://10.10.173.203/api/v1/namespaces/default/pods?limit=500 89 | // GET https://10.10.173.203/api/v1/namespaces/kube-system/pods?limit=500 90 | // GET https://10.10.173.203/api/v1/namespaces/kube-system/pods/kube-dns-5b54cf547c-jl4r9 91 | result := restClient.Get(). 92 | Namespace("kube-system"). 93 | Resource("pods"). 94 | Name("kube-dns-5b54cf547c-jl4r9"). 95 | Do() 96 | bytes, err := result.Raw() 97 | if err != nil { 98 | fmt.Printf("%s: %s\n", err.Error(), bytes) 99 | } else { 100 | fmt.Printf("%s\n", bytes) 101 | } 102 | 103 | //方法2:从 clientSet 中获取 104 | restInterface, err := GetCoreRestClient(config) 105 | if err != nil { 106 | glog.Fatal(err.Error()) 107 | return 108 | } 109 | 110 | result = restInterface.Get(). 111 | Namespace("kube-system"). 112 | Resource("pods"). 113 | Name("kube-dns-5b54cf547c-jl4r9"). 114 | Do() 115 | bytes, err = result.Raw() 116 | if err != nil { 117 | fmt.Printf("%s: %s\n", err.Error(), bytes) 118 | } else { 119 | fmt.Printf("%s\n", bytes) 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /opentracingusage/00-quickstart/quickstart.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "log" 6 | 7 | opentracing "github.com/opentracing/opentracing-go" 8 | oplog "github.com/opentracing/opentracing-go/log" 9 | jaeger "github.com/uber/jaeger-client-go" 10 | jaegercfg "github.com/uber/jaeger-client-go/config" 11 | jaegerlog "github.com/uber/jaeger-client-go/log" 12 | "github.com/uber/jaeger-lib/metrics" 13 | ) 14 | 15 | func initJaeger(service, addr string) (opentracing.Tracer, io.Closer, error) { 16 | cfg := jaegercfg.Configuration{ 17 | ServiceName: service, 18 | Sampler: &jaegercfg.SamplerConfig{ 19 | Type: jaeger.SamplerTypeConst, 20 | Param: 1, 21 | }, 22 | Reporter: &jaegercfg.ReporterConfig{ 23 | LogSpans: true, 24 | LocalAgentHostPort: addr, 25 | }, 26 | } 27 | jLogger := jaegerlog.StdLogger 28 | jMetricsFactory := metrics.NullFactory 29 | 30 | return cfg.NewTracer( 31 | jaegercfg.Logger(jLogger), 32 | jaegercfg.Metrics(jMetricsFactory), 33 | ) 34 | } 35 | 36 | //docker run -d -p 6831:6831/udp -p 16686:16686 jaegertracing/all-in-one:latest 37 | func main() { 38 | tracer, closer, err := initJaeger("00-quickstart", "127.0.0.1:6831") 39 | if err != nil { 40 | log.Fatal(err.Error()) 41 | } 42 | defer closer.Close() 43 | opentracing.SetGlobalTracer(tracer) 44 | 45 | rootspan := opentracing.StartSpan("rootcall") 46 | defer rootspan.Finish() 47 | rootspan.SetTag("rootcall", "rootcall") 48 | 49 | subspan := opentracing.StartSpan("subcall", 50 | opentracing.ChildOf(rootspan.Context())) 51 | defer subspan.Finish() 52 | subspan.SetTag("subcall", "subcall") 53 | subspan.LogFields(oplog.String("event", "testlog")) 54 | } 55 | -------------------------------------------------------------------------------- /opentracingusage/01-httptrace/httpreq.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "go-code-example/opentracingusage" 5 | "log" 6 | "net/http" 7 | "time" 8 | 9 | opentracing "github.com/opentracing/opentracing-go" 10 | "github.com/opentracing/opentracing-go/ext" 11 | ) 12 | 13 | func server() { 14 | tracer := opentracing.GlobalTracer() 15 | http.HandleFunc("/publish", func(w http.ResponseWriter, r *http.Request) { 16 | spanctx, _ := tracer.Extract(opentracing.HTTPHeaders, 17 | opentracing.HTTPHeadersCarrier(r.Header)) 18 | serverspan := tracer.StartSpan("server", ext.RPCServerOption(spanctx)) 19 | defer serverspan.Finish() 20 | }) 21 | log.Fatal(http.ListenAndServe(":8082", nil)) 22 | } 23 | 24 | func client() { 25 | url := "http://localhost:8082/publish" 26 | req, _ := http.NewRequest("GET", url, nil) 27 | 28 | tracer := opentracing.GlobalTracer() 29 | 30 | clientSpan := tracer.StartSpan("client") 31 | defer clientSpan.Finish() 32 | 33 | ext.SpanKindRPCClient.Set(clientSpan) 34 | ext.HTTPUrl.Set(clientSpan, url) 35 | ext.HTTPMethod.Set(clientSpan, "GET") 36 | 37 | tracer.Inject(clientSpan.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header)) 38 | http.DefaultClient.Do(req) 39 | } 40 | 41 | func main() { 42 | tracer, closer, err := opentracingusage.InitJaeger("01-httptrace", "127.0.0.1:6831") 43 | if err != nil { 44 | log.Fatal(err.Error()) 45 | } 46 | defer closer.Close() 47 | opentracing.SetGlobalTracer(tracer) 48 | 49 | go server() 50 | 51 | time.Sleep(1 * time.Second) 52 | client() 53 | } 54 | -------------------------------------------------------------------------------- /opentracingusage/common.go: -------------------------------------------------------------------------------- 1 | package opentracingusage 2 | 3 | import ( 4 | "io" 5 | 6 | opentracing "github.com/opentracing/opentracing-go" 7 | jaeger "github.com/uber/jaeger-client-go" 8 | 9 | jaegercfg "github.com/uber/jaeger-client-go/config" 10 | jaegerlog "github.com/uber/jaeger-client-go/log" 11 | "github.com/uber/jaeger-lib/metrics" 12 | ) 13 | 14 | func InitJaeger(service, addr string) (opentracing.Tracer, io.Closer, error) { 15 | cfg := jaegercfg.Configuration{ 16 | ServiceName: service, 17 | Sampler: &jaegercfg.SamplerConfig{ 18 | Type: jaeger.SamplerTypeConst, 19 | Param: 1, 20 | }, 21 | Reporter: &jaegercfg.ReporterConfig{ 22 | LogSpans: true, 23 | LocalAgentHostPort: addr, 24 | }, 25 | } 26 | jLogger := jaegerlog.StdLogger 27 | jMetricsFactory := metrics.NullFactory 28 | 29 | return cfg.NewTracer( 30 | jaegercfg.Logger(jLogger), 31 | jaegercfg.Metrics(jMetricsFactory), 32 | ) 33 | } 34 | --------------------------------------------------------------------------------