go learning
1. vim-go
https://github.com/fatih/vim-go-tutorial
curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim git clone https://github.com/fatih/vim-go.git ~/.vim/plugged/vim-go
echo "
call plug#begin()
Plug 'fatih/vim-go', { 'do': ':GoInstallBinaries' }
call plug#end()set autowrite
" >>~/.vimrc
代码质量:go vet, golint, goimports
2. 学习资料
快速入门:
https://github.com/a8m/go-lang-cheat-sheet
官方文档:
spec: https://golang.org/ref/spec
go-tour: https://tour.golang.org/list
blog: https://blog.golang.org/index
深入解析Go 这本书,分析了很多特例。 值得一看。
https://tiancaiamao.gitbooks.io/go-internals/content/zh/03.6.html
The author Brian W. Kernighan is also write the 大名鼎鼎的 <The C Programming Lanuaguage>
Go 语言设计与实现 (新书)
在线练习 https://play.golang.org/p/e81LuPO_JR
3. 对比学习
如果熟悉C的话,可以对比学习go
4. 继承
$ cat base.go
1 package base 2 3 type BaseT struct { 4 a int 5 b int 6 } 7 8 func (b *BaseT) Add() int{ 9 return b.a+b.b 10 } 11 12 func (b *BaseT) Sub() int { 13 return b.a-b.b 14 } 15 16 17 type Bf interface { 18 Add() int 19 } 20 21 func NewBasetT(a, b int) *BaseT{ 22 return &BaseT{a, b} 23 }
$ cat test.go
1 package main 2 3 import ( 4 "fmt" 5 "base" 6 ) 7 8 9 type BaseT struct{ 10 base.BaseT 11 a int 12 b int 13 } 14 15 func (b *BaseT) Add() int{ 16 return b.a+b.b 17 } 18 19 func main() { 20 nb := base.NewBasetT(1, 2) 21 b := &BaseT{*nb, 3, 4} 22 fmt.Println(b.Add()) 23 }
5. 内存指针转换为 slice
var ptr unsafe.Pointer
s := ((*[1<<10]byte)(ptr))[:200]
这里数组大小其实是假的。s
是一个200个元素的slice。
这种方式其实是做了内存copy
或者这种方式:
var ptr unsafe.Pointer
var s1 = struct {
addr uintptr
len int
cap int
}{ptr, length, length}
s := *(*[]byte)(unsafe.Pointer(&s1))
这种方式就是引用原内存的东西。
6. go 缺失了python的动态特性。 不过可以用reflect进行一些扩展。
http://studygolang.com/articles/4892
通过断言来动态获取接口类型,还是有些傻
接口实现原理, 简易介绍。还是看官方文档。
json转map,可以直接看官方文档。
7. 传递接口实现多态。
8. 优化
9. disclouser in filepath.Walk
https://xojoc.pw/justcode/golang-file-tree-traversal.html
10. go 第三方库
https://golanglibs.com/top?q=process+list
11. golang re
https://golang.org/pkg/regexp/syntax/
12. 排序例子
https://gobyexample.com/sorting-by-functions
13. 循环变量快照
在5.6.1中有讲解
在循环的闭包 引用循环变量存在这个问题。
14. 排空channel
goroutine泄露(§8.4.4)
15. 内部变量不能够在函数外部被访问到
变量(§2.3.4)在没有被转义的情况下是无法在函数外部访问的
16. plugin
since go_lang 1.8, we can use rpc for plugin.
rpc plugin: https://github.com/dkiser/go-plugin-example
more explain for 1.8 plugin:
https://jeremywho.com/go-1.8---plugins/
picture show the 1.8 plugin
https://github.com/grsmv/go-plugin-example
https://github.com/vladimirvivien/go-plugin-example
https://github.com/hashicorp/go-plugin
17. testcase
https://semaphoreci.com/community/tutorials/how-to-test-in-go
https://blog.golang.org/examples
https://golang.org/pkg/testing/
18. goroutine
19. nested struct
https://stackoverflow.com/questions/24809235/initialize-a-nested-struct-in-golang
20. 第三方库
https://github.com/avelino/awesome-go
21. string 求最大值
sort.Sort(sort.Reverse(sort.StringSlice(s)))
22. errror handling
https://blog.golang.org/error-handling-and-go
23. golang net/http self-sign certification.
One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
https://golang.org/pkg/net/http/#ListenAndServeTLS
24. personal experience
http://www.jianshu.com/u/1381dc29fed9 _张晓龙_ 的blog不错。详细介绍了怎么写testcase。
26. net/http unix socket example
https://gist.github.com/hakobe/6f70d69b8c5243117787fd488ae7fbf2
27. golang command
http://wiki.jikexueyuan.com/project/go-command-tutorial/0.7.html
28. golang.org blog
https://blog.golang.org/defer-panic-and-recover
29. grpc
chinese doc: http://doc.oschina.net/grpc?t=60133
30. protobuf
https://developers.google.com/protocol-buffers/docs/overview
install: https://github.com/google/protobuf/blob/master/src/README.md
readme: https://github.com/google/protobuf/blob/master/README.md
31. go offical RPC example
https://play.golang.org/p/4BZQbM9lNN
1 package main 2 3 import ( 4 "io" 5 "log" 6 "net/rpc" 7 ) 8 9 type pipePair struct { 10 reader *io.PipeReader 11 writer *io.PipeWriter 12 } 13 14 func (this *pipePair) Read(p []byte) (int, error) { 15 return this.reader.Read(p) 16 } 17 18 func (this *pipePair) Write(p []byte) (int, error) { 19 return this.writer.Write(p) 20 } 21 22 func (this *pipePair) Close() error { 23 this.writer.Close() 24 return this.reader.Close() 25 } 26 27 type Serv struct { 28 token string 29 } 30 31 func (this *Serv) SetToken(token string, dummy *int) error { 32 this.token = token 33 return nil 34 } 35 36 func (this *Serv) GetToken(dummy int, token *string) error { 37 *token = this.token 38 return nil 39 } 40 41 type Registrar struct { 42 } 43 44 func (this *Registrar) Register(name string, dummy *int) error { 45 rpc.RegisterName(name, new(Serv)) 46 return nil 47 } 48 49 func server(pipes pipePair) { 50 rpc.Register(new(Registrar)) 51 rpc.ServeConn(&pipes) 52 } 53 54 func main() { 55 var token string 56 var in, out pipePair 57 in.reader, out.writer = io.Pipe() 58 out.reader, in.writer = io.Pipe() 59 go server(out) 60 client := rpc.NewClient(&in) 61 // Register some objects 62 client.Call("Registrar.Register", "First", nil) 63 client.Call("Registrar.Register", "Second", nil) 64 // Assign token values individually 65 client.Call("First.SetToken", "abc", nil) 66 client.Call("Second.SetToken", "def", nil) 67 // Now try to read them 68 client.Call("First.GetToken", 5, &token) 69 log.Printf("first token is %v", token) 70 client.Call("Second.GetToken", 5, &token) 71 log.Printf("second token is %v", token) 72 }
32. golang process drop privilege
https://play.golang.org/p/dXBizm4xl3
1 package main 2 3 import ( 4 "fmt" 5 "net" 6 "net/http" 7 "os" 8 "os/exec" 9 "syscall" 10 ) 11 12 func main() { 13 if os.Getuid() == 0 { 14 fmt.Println("Dropping privileges...") 15 if err := drop(); err != nil { 16 fmt.Println("Failed to drop privileges:", err) 17 os.Exit(1) 18 } 19 } 20 21 l, err := net.FileListener(os.NewFile(3, "[socket]")) 22 if err != nil { 23 // Yell into the void. 24 fmt.Println("Failed to listen on FD 3:", err) 25 os.Exit(1) 26 } 27 28 http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 29 fmt.Fprintf(w, "I am process %d running as %d/%d", os.Getpid(), os.Getuid(), os.Getgid()) 30 })) 31 } 32 33 func drop() error { 34 l, err := net.Listen("tcp", ":80") 35 if err != nil { 36 return err 37 } 38 39 f, err := l.(*net.TCPListener).File() 40 if err != nil { 41 return err 42 } 43 44 cmd := exec.Command(os.Args[0]) 45 cmd.ExtraFiles = []*os.File{f} 46 cmd.SysProcAttr = &syscall.SysProcAttr{ 47 Credential: &syscall.Credential{ 48 Uid: 65534, 49 Gid: 65534, 50 }, 51 Setsid: true, 52 } 53 54 if err := cmd.Start(); err != nil { 55 return err 56 } 57 58 fmt.Printf("Spawned process %d, exiting\n", cmd.Process.Pid) 59 cmd.Process.Release() 60 os.Exit(0) 61 return nil /* unreachable */ 62 }
文若的python实现: https://www.ovirt.org/develop/release-management/features/infra/supervdsm-service/
in golang father to notify child: https://github.com/opencontainers/runc/blob/master/libcontainer/system/linux.go
33. // Create a timer that will kill the process
cmd.Process.Signal http://www.darrencoxall.com/golang/executing-commands-in-go/
34. difference os.Pipe and io.Pipe
io.Pipe: https://golang.org/pkg/io/#Pipe Pipe creates a synchronous in-memory pipe
os.Pipe: https://golang.org/pkg/os/#Pipe Pipe returns a connected pair of Files;
35. os signal Notify
Notify: https://golang.org/pkg/os/signal/#example_Notify
36. tls revoke
https://github.com/cloudflare/cfssl/tree/master/revoke
37. print struct name
https://stackoverflow.com/questions/24512112/how-to-print-struct-variables-in-console
38. all channel exit.
39. Singleton Pattern in Go
http://marcio.io/2015/07/singleton-pattern-in-go/
40. slice操作
Appending to a slice
https://tour.golang.org/moretypes/15
Correct way to initialize empty slice
41. 变参数
42. 类型转换
How to convert string from interface to []string in golang?
Convert []string to []interface{}
casting interface{} to string array
Partly JSON unmarshal into a map in Go
Print a Variable's Type (e.g. Int, String, Float)
43. exmaple
union union 类型(即sum types)在golang语言中的实现
Go by Example: String Formatting
fmt.Printf formatting tutorial and cheat sheet
Go by Example: Command-Line Flags
Go by Example: Command-Line Arguments
kubebuilder中type func 简化实验
1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 ) 7 8 type NamespacedName struct { 9 Namespace string 10 Name string 11 } 12 13 type Request struct { 14 // NamespacedName is the name and namespace of the object to reconcile. 15 NamespacedName 16 } 17 18 type Object interface { 19 GetObjectKind(MapObject) []Request 20 } 21 22 type MapObject struct { 23 Object Object 24 } 25 26 type ObjectIns struct { 27 Name string 28 } 29 30 func (o ObjectIns) GetObjectKind(i MapObject) []Request { 31 var enqueueRequest []Request 32 return enqueueRequest 33 } 34 35 // mapper maps an object to a collection of keys to be enqueued 36 type mapper interface { 37 // Map maps an object 38 Map(MapObject) []Request 39 } 40 41 type EventHandler interface { 42 Create(string, string) 43 } 44 type enqueueRequestsFromMapFunc struct { 45 // Mapper transforms the argument into a slice of keys to be reconciled 46 ToRequests mapper 47 } 48 49 func (e *enqueueRequestsFromMapFunc) Create(evt string, q string) { 50 fmt.Println(evt, q) 51 } 52 53 // var _ EventHandler = &enqueueRequestsFromMapFunc{} 54 55 type toRequestsFunc func(MapObject) []Request 56 57 func EnqueueRequestsFromMapFunc(mapFN func(MapObject) []Request) EventHandler { 58 return &enqueueRequestsFromMapFunc{ 59 ToRequests: toRequestsFunc(mapFN), 60 } 61 } 62 63 func (m toRequestsFunc) Map(i MapObject) []Request { 64 return m(i) 65 } 66 func (m toRequestsFunc) Say() { 67 fmt.Println("Function sets, say hello") 68 } 69 70 func GetToRequestsFunc(r string, crliststruct string) func(h MapObject) []Request { 71 72 return func(h MapObject) []Request { 73 fmt.Println("GetToRequestsFunc r parameter", r) 74 fmt.Println("GetToRequestsFunc crliststruct parameter", crliststruct) 75 var enqueueRequest []Request 76 req := Request{ 77 NamespacedName: NamespacedName{ 78 Name: "meta.GetName", 79 Namespace: "meta.GetNamespace()", 80 }} 81 enqueueRequest = append(enqueueRequest, req) 82 83 return enqueueRequest 84 } 85 } 86 87 type CniInterfaceStatus struct { 88 // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 89 // Important: Run "make" to regenerate code after modifying this file 90 NetName string `json:"name,omitempty"` 91 Name string `json:"interface,omitempty"` 92 GatWay string `json:"gateway,omitempty"` 93 IpAddress interface{} `json:"ipAddress,omitempty"` 94 } 95 96 type Annotations struct { 97 Type string `json:"type,omitempty"` 98 Interface []CniInterfaceStatus `json:"interface,omitempty"` 99 } 100 101 func Interface2IpAddressArray(addriface interface{}) []string { 102 var iparray []string 103 switch addriface.(type) { 104 case []interface{}: 105 for _, aif := range addriface.([]interface{}) { 106 iparray = append(iparray, aif.(string)) 107 } 108 case string: 109 iparray = append(iparray, addriface.(string)) 110 default: 111 iparray = []string{} 112 } 113 return iparray 114 } 115 116 func main() { 117 fmt.Println("Hello, playground") 118 oi := ObjectIns{Name: "ObjectIns"} 119 mo := MapObject{Object: oi} 120 a := GetToRequestsFunc("requert", "test") 121 fmt.Println("=======================") 122 fmt.Println(a(mo)) 123 fmt.Println("=======================") 124 fmt.Println(&a) 125 TR := toRequestsFunc(a) 126 fmt.Println(TR) 127 TR.Say() 128 fmt.Println("=======================") 129 TR.Map(mo) // == a(mo) 130 fmt.Println("=======================") 131 132 eq := &enqueueRequestsFromMapFunc{ToRequests: toRequestsFunc(a)} 133 fmt.Println(eq) 134 // &EnqueueRequestsFromMapFunc{TR: "xxxx"} 135 jsonstr := `{ "type": "ovn4nfv", "interface": [{"name": "ovn-network", "interface": "net0", "ipAddress": ["$cnfLan0"]}, {"name": "pnetwork", "interface": "net1", "ipAddress": "$cnfWan0", "gateway": "$cnfWanGateway"}]}` 136 var dat map[string]interface{} 137 // var cniInterfaceStatus CniInterfaceStatus 138 var annotations Annotations 139 // err = json.Unmarshal([]byte(jsonstr), &cniInterfaceStatus) 140 if err := json.Unmarshal([]byte(jsonstr), &dat); err != nil { 141 panic(err) 142 } 143 ifc := dat["interface"].([]interface{})[0] 144 fmt.Println(ifc.(map[string]interface{})["interface"].(string)) 145 //for k, v := range ifc.(map[string]interface){ 146 // fmt.Println(k, v) 147 //} 148 // fmt.Println(ifc.(CniInterfaceStatus)) 149 if err := json.Unmarshal([]byte(jsonstr), &annotations); err != nil { 150 panic(err) 151 } 152 fmt.Println(annotations) 153 ipa := annotations.Interface[0].IpAddress 154 for _, itf := range annotations.Interface { 155 fmt.Println(itf) 156 fmt.Println("--------------------") 157 } 158 var ipas []string 159 switch v := ipa.(type) { 160 case []interface{}: 161 b, ok := ipa.([]string) 162 fmt.Println("Bag类型 :", ok, "数据", b) 163 for _, iF := range ipa.([]interface{}) { 164 ipas = append(ipas, iF.(string)) 165 } 166 fmt.Println("ipas:", ipas) 167 fmt.Printf("Twice %v is %v\n", v, len(v)) 168 case string: 169 fmt.Printf("%q is %v bytes long\n", v, len(v)) 170 default: 171 fmt.Printf("I don't know about type %T!\n", v) 172 } 173 if annotations.Interface[0].GatWay != "" { 174 fmt.Println(annotations.Interface[0].GatWay) 175 } 176 fmt.Println(Interface2IpAddressArray(annotations.Interface[1].GatWay)) 177 }
time.Sleep() Function in Golang With Examples channel 传递timeout
不同接口之间的转换 (多的可以向少的转换,反之不可
)
//不同接口之间的转换,类似于Java中的向上转型,或者向下转型 //就是说,有两个接口A, B //其中,A接口里,嵌入了B //那么A接口可以转换成B接口,但是,B接口不能转换成A接口,因为 //A接口里,可能包含B接口里没有的方法 //也就是说,多的可以向少的转换,反之不可。 package main import "fmt" type USB2 interface { Name() string Connecter } type Connecter interface { Connect() } type PcConnecter struct { name string } func (pcConnecter PcConnecter)Name() string { return pcConnecter.name } func(pcConnecter PcConnecter)Connect() { fmt.Println("Connected:\t", pcConnecter.name) } func main() { pc := PcConnecter{"appleConnector"} var a Connecter //将USE2 类型,强制 转换成了Connecter类型 a = Connecter(pc) a.Connect() //------验证----只有当接口存储的类型和对象都为nil时,接口才等于nil //声明一个空接口, 也没有赋值,就是nil var aa interface{} fmt.Println( aa == nil) // aa 本身就是一个nil,啥也没存 //变量p, 是一个指向int类型的指针 //直接初始化为nil var p *int = nil aa = p //aa 指向p fmt.Println( aa == nil) }
组合需要与接口结合使用才能体现其精髓。
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 type IHello interface { 8 Hello(name string) 9 } 10 11 type A struct { 12 } 13 14 func (*A) Hello(name string) { 15 fmt.Println("hello " + name + ", i am a") 16 } 17 18 type D struct { 19 } 20 21 func (*D) Hello(name string) { 22 fmt.Println("hello " + name + ", i am d") 23 } 24 25 type B struct { 26 *A 27 } 28 29 type C struct { 30 IHello 31 } 32 33 func main() { 34 name := "Lee" 35 a := A{} 36 a.Hello(name) //hello Lee, i am a 37 38 b := B{&A{}} 39 b.Hello(name) //hello Lee, i am a 40 41 c := C{&A{}} 42 c.Hello(name) //hello Lee, i am a 43 44 c = C{&D{}} 45 c.Hello(name) //hello Lee, i am d 46 }
A的指针继承了接口IHello, B中嵌入了具体实现类A,C中嵌入了接口IHello,
B C两者在赋值时,均可嵌入A的指针实例,但是C可以根据运行时上下文指定具体实现,更加灵活。
面向接口编程,提倡共用组合与接口的优雅代码
Golang中的面向对象继承
slice
Go Slices: usage and internals
Introduction to Slices in Golang
s := []struct { i int b bool }{ {2, true}, {3, false}, {5, true}, {7, true}, {11, false}, {13, true}, } fmt.Println(s)
Go 中 Set 的实现方式
2 basic set implementations
The Go Programming Language Specification
golang 上下文 Context