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

    了解go的基础数据类型

官方文档:

    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

 

Go语言圣经(中文版)  

The author Brian W. Kernighan is also write the 大名鼎鼎的  <The C Programming Lanuaguage>

 

Go 语言设计与实现   (新书)

go入门指南  

学习go语言

在线练习  https://play.golang.org/p/e81LuPO_JR

丰富的example

go web 开发

在线文档

 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 }
View Code

 

$ 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 }
View Code

 

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

此外可以使用接口进行类似弱类型参数传递。

传递时需要注意的问题。

通过断言来动态获取接口类型,还是有些傻

接口实现原理, 简易介绍。还是看官方文档。

map转structexample

json转map,可以直接看官方文档。

使用reflect来设置struc field

7. 传递接口实现多态。

 接口的操作

8. 优化

map 并发优化 map的操作跟python差不多

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

more example for plugin.

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

golang的goroutine是如何实现的

运行时启动过程

 

19. nested struct

https://stackoverflow.com/questions/24809235/initialize-a-nested-struct-in-golang

 

20. 第三方库

https://golanglibs.com/

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

office link

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 }
View Code

 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 }
View Code

 

文若的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

https://github.com/mindreframer/golang-devops-stuff/blob/master/src/github.com/dotcloud/docker/vendor/src/github.com/docker/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.

https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/

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. 变参数

Go 语言“可变参数函数”终极指南 

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: Switch 

Type switches    

Go by Example: JSON

Go by Example: String Formatting   

fmt.Printf formatting tutorial and cheat sheet   

golang中 type func() 用法分析  

pkg/fmt

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 }
View Code

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 }
View Code

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

理解go的function types

 

The Go Programming Language Specification   

golang 上下文 Context  

 

 

posted @ 2017-02-13 18:08  lvmxh  阅读(410)  评论(0编辑  收藏  举报