Go基础学习

一、安装sublime与安装PackageControl

  1、下载Sublime Text:http://www.sublimetext.com/3。选择windows64位下载安装。

  2、安装过程中记得选择“Add to explorer context menu”,把它加入右键快捷菜单。其它以默认设置安装。

  3、安装插件,插件网址:https://packagecontrol.io/,如果能打开就在线安装.
       安装 Package Control(在线安装)
      通过快捷键 ctrl+`` 或者菜单 View > Show Console 或者菜单 视图 > 显示/隐藏控制台 进入控制台,复制下面的代码到控制台运行

   4、但是这个网站无法安装packagecontrol因为打不开,所以打不开选择在这下载离线安装:https://github.com/HBLong/channel_v3_daily

           下载好后解压,将Package Control.sublime-package文件复制,打开菜单 - Preferences - Browser Package进入文件夹,当前文件地址是 Sublime Text 3\Packages,我们进入到Sublime Text 3\Installed           Packages文件夹下,将复制的Package Control.sublime-package文件粘贴到目录下,重启Sublime Text3。打开菜单 - Preferences看到下面有package setting和package control就安装好了

二、sublime text3安装并解决Gosublime无法自动补全代码

  安装Gosublime

    打开Perferences–Browse Packages…,进入Gosublime,在命令行里输入:

    git clone https://github.com/DisposaBoy/GoSublime.git    

  自动补全解决方法
    在windows和mac上使用sublime text3安装Gosublime插件后都无法自动补全代码,经过多日的研究找到如下解决方法。
    打开Perferences–Browse Packages…,进入Gosublime:
    1、在src目录下创建margo目录;
    2、拷贝src/margo.sh/extension-example/extension-example.go文件到margo目录下;
    3、拷贝margo文件夹(所有文件和目录)到src/margo.sh/vendor目录下;
    4、重新打开sublime text3,稍等几分钟就可以自动补全代码了。

三、Go 语言环境安装

四、Go语言结构

 1 //定义了包名。你必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包
 2 package main
 3 
 4 //import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包
 5 import (
 6     "fmt"
 7 )
 8 
 9 //func main() 是程序开始执行的函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)
10 func main() {
11     fmt.Print("Hello,World!")
12 }
13 
14 //go run test.go运行

五、数据类型

六、切片

 1 var s = []int{2, 3, 4}
 2 
 3     //make是长度为3,5最大长度
 4     var numbers = make([]int, 3, 5)
 5 
 6     var number2 = []int{2, 3, 3, 4, 4, 3, 4}
 7 
 8     //s5的长度4,容量是7
 9     s5 := number2[:4]
10     //s6的长度是4,容量也是4
11     s6 := number2[3:]
12 
13     var countnum = len(number2)
14 
15     //append追加元素
16     number2 = append(number2, 3, 3, 3)
17     for i, num := range number2 {
18     }

七、闭包

  1、 闭包是匿名函数与匿名函数所引用环境的组合。匿名函数有动态创建的特性,该特性使得匿名函数不用通过参数传递的方式,就可以直接引用外部的变量。这就类似于常规函数直接使用全局变量一样,个人理解为:匿名函数和它引用的变量以及环境,类似常规函数引用全局变量处于一个包的环境。

 1 package main
 2 
 3 //import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包
 4 import (
 5     "fmt"
 6 )
 7 
 8 // 闭包
 9 // 闭包是匿名函数与匿名函数所引用环境的组合。匿名函数有动态创建的特性,该特性使得匿名函数不用通过参数传递的方式,就可以直接引用外部的变量。这就类似于常规函数直接使用全局变量一样,个人理解为:匿名函数和它引用的变量以及环境,类似常规函数引用全局变量处于一个包的环境。
10 
11 //1、闭包作为函数返回值
12 func Increase() func() int {
13     n := 0
14     return func() int {
15         fmt.Printf("%p\n", &n)
16         n++
17         return n
18     }
19 }
20 
21 func main() {
22     //1、闭包
23     n := 0
24     f := func() int {
25         //匿名函数引用外部的变量
26         n += 1
27         return n
28     }
29     fmt.Println(f()) // 别忘记括号,不加括号相当于地址
30     fmt.Println(f())
31 
32     //2、闭包最为返回值
33     //闭包被返回赋予一个同类型的变量时,同时赋值的是整个闭包的状态,
34     //该状态会一直存在外部被赋值的变量in中,直到in被销毁,整个闭包也被销毁。
35     in := Increase()
36     fmt.Println(in()) //输出1
37     fmt.Println(in()) //输出2
38 }

  2、闭包的应用

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 //隔离数据
 8 // 函数计数器
 9 func counter(f func()) func() int {
10     n := 0
11     return func() int {
12         f()
13         n += 1
14         return n
15     }
16 }
17 
18 // 测试的调用函数
19 func foo() {
20     fmt.Println("call foo")
21 }
22 
23 func main() {
24     cnt := counter(foo)
25     cnt()
26     cnt()
27     cnt()
28     fmt.Println(cnt())
29 }

  3、装饰函数和创建中间件

 1 func wrapping(f func() string) {
 2     fmt.Println("do my work...")
 3     fmt.Println("wrapping function: ", f())
 4     fmt.Println("my work finished !")
 5 }
 6 
 7 func sayHello() string {
 8     return "Hello !"
 9 }
10 
11 func sayByeBye() string {
12     return "Bye Bye !"
13 }
14 
15 func main() {
16     wrapping(sayHello)
17     wrapping(sayByeBye)
18 }

   4、将不匹配参数的函数的函数进行应用

 1 package main
 2 
 3 //import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包
 4 import (
 5     "fmt"
 6 )
 7 
 8 func f1(f func()) {
 9     fmt.Println("This f1")
10     f()
11 }
12 
13 func f2(x, y int) {
14     fmt.Println("this f2 ")
15     fmt.Println(x + y)
16 }
17 
18 //f3对f2进行包装,返回一个不带参数的函数
19 func f3(a func(x, y int), x, y int) func() {
20     tmp := func() {
21         a(x, y)
22     }
23     return tmp
24 }
25 
26 func main() {
27     //将f2传入到f1
28     //将类型不匹配的函数应用到函数参数中
29     var tmpf3 = f3(f2, 3, 4)
30     f1(tmpf3)
31 }

   5、延迟调用

 1 func main() {
 2     x, y := 1,2
 3 
 4     defer func(a int){
 5         fmt.Println("defer x, y = ", a, y) //y为闭包引用
 6     }(x) //x值拷贝 调用时传入参数
 7 
 8     x += 100
 9     y += 200
10 
11     fmt.Println(x, y)
12 }

七、defer语句

  1、defer有延迟调用的特性,处理资源清理、文件关闭、解锁及记录时间等

  2、defer执行时间,在go语言函数中,return语句不是原子操作,它分为给返回值赋值和RET指令两步,而defer语句执行的时机就在返回值赋值操作后

  

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func f1() int {
 8     x := 5
 9     defer func() {
10         x++
11     }()
12     return x //1、返回值进行赋值  2执行defer  3真正的ret指令
13 }
14 
15 func f2() (x int) {
16     defer func() {
17         x++
18     }()
19     return 5 //1/5返回给了x,2执行了defer里面x++进行运算
20 }
21 
22 func f3() (y int) {
23     x := 5
24     defer func() {
25         x++
26     }()
27     return x //x=5 赋值给ret给了y 而defer该了x的值
28 }
29 
30 func f4() (x int) {
31     defer func() {
32         x++ //改变了x是参数,跟return返回的x无关
33     }(x)
34     return 5 //
35 }
36 
37 func f5() (x int) {
38     defer func() {
39         x++      //改变了x是参数,跟return返回的x无关
40         return x //defer中return值跟f5return值无关
41     }(x)
42     return 5 //
43 }
44 
45 func f6() (x *int) {
46     defer func() {
47         (*x)++ //defter是指针,是指向x数据的地址
48     }(&x)
49     return 5 //
50 }
51 
52 func calc(index string, a, b int) int {
53     ret := a + b
54     fmt.Println(index, a, b, ret)
55     return ret
56 }
57 
58 func main() {
59     fmt.Print(f1())
60     fmt.Print(f2())
61     fmt.Print(f3()) //5
62     fmt.Print(f4()) //5
63 
64     //最后执行defer,calc会先将参数进行计算出来
65     defer calc("1", a, calc("10", a, b))
66 }

八、内置函数

  1、new 用来分配内存,主要用于分配值类型,int/string, 返回时指针类型

  2、make用来分配内存,主要分配引用类型,比如chan/map/slice

  3、panic/recover  在go1.12是没有异常处理机制的,但是使用panic/revocer模式来处理错误。panic任何地方引发,但recover只有在defer调用中有效

package main

import (
    "fmt"
)

func func1() {
    defer func() {
        //获取错误,recover进行修复
        err := recover()
        fmt.Println("释放数据库连接")
    }()
    panic("出现错误")
    fmt.Println("b")
}

func main() {
    func1()
}

   4、recover必须搭配在refer使用,defer一定要在可能引发panic的语句之前定义

九、fmt库介绍

  fmt.printf("%d %f %p指针")

  fmt.sprintf()

十、自定义类型与别名

  1、type myInt int ,自定义类型,给类型加入方法

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 type myInt int
 8 
 9 func main() {
10     var n myInt
11     n = 100
12 
13     u := 100
14 
15     //int32的类型
16     var c rune
17     c = '中'
18 }

十一、结构体

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 type myInt int
 8 
 9 type Person struct {
10     name string
11     age  int32
12 }
13 
14 //传递结构体指针
15 func f(x *Person) {
16     (*x).age = 1
17 }
18 
19 func main() {
20     // var n myInt
21     // n = 100
22     // u := 100
23     // //int32的类型
24     // var c rune
25     // c = '中'
26 
27     //返回一个指针,指向了结构体
28     var p2 = new(Person)
29     fmt.Printf("值==%x", p2)
30     fmt.Printf("值==%x", &(*p2))
31     fmt.Printf("type==%T", p2)
32 
33     //声明变量并且初始化
34     var p3 = Person{
35         name: "lxw",
36         age:  1,
37     }
38 
39     //定义临时的变量
40     var s struct {
41         x string
42         y int
43     }
44 }

 十二、接口

  

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 //定义接口
 8 type speaker interface{
 9     speak()
10 }
11 
12 type cat struct{
13     name string
14     feet int8
15 }
16 
17 //实现接口speaker方法
18 // func (c cat) speak() {
19     
20 // }
21 
22 func (c *cat) speak() {
23     
24 }
25 
26 func da(x speaker) {
27     x.speak()
28 }
29 
30 func main() {
31     var c1 = new(cat)
32     c2 := cat{"tom", 4}
33 }

 

  多个类型实现接口
  同一个结构体实现多个接口

  接口还可以嵌套接口

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 //多个类型实现接口
 8 //同一个结构体实现多个接口
 9 
10 //接口还可以嵌套接口
11 type animal interface{
12     mover
13     eater
14 }
15 
16 //空接口, 可以接受任何类型,所有的类型都实现了空接口
17 //...表示接受多个任何类型
18 func print_me(a ...interface{}) {
19     fmt.Printf("type %T", a)
20 }
21 
22 
23 //mover接口
24 type mover interface{
25     move()
26 }
27 
28 //eater接口
29 type eater interface{
30     eat(string)
31 }
32 
33 type cat struct {
34     name string
35     age int8
36 }
37 
38 func (c *cat) move() {
39     fmt.Println("xxxxxxxxxxx")
40 }
41 
42 func (c *cat) eat(food string) {
43     fmt.Println("xxxxxxxxx")
44 }
45 
46 func main() {
47     var m1 map[string]interface{}
48     m1 = make(map[string]interface{}, 16)
49     m1["name"] = "linxiannwei"
50     m1["age"] = 9000
51     m1["hobby"] = [...]string{"", ""}
52 }

  2、判断空接口 x.(T)  x表示类型interface{}变量,T表示断言x可能的类型

    t := a.(type)获取接口动态的类型

  

 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 //判断空接口的类型 x.(T)  x表示类型interface{}变量,T表示断言x可能的类型
 8 func assign(a interface{}) {
 9     str, ok := a.(string)
10     if !ok {
11         //ok表示string类型
12     }else{
13 
14     }
15 
16     t := a.(type)
17 
18     switch t {
19     case string:
20         fmt.Println("是的字符串")
21     case int:
22     case bool:
23         
24     }
25 
26 }
27 
28 func main() {
29     
30 }

 十三、package使用

  在文件夹code.number.cal有calc.go

1 package calc
2 
3 //包中的标识符(变量名、函数名、结构体、接口等)如果首字母小写的,表示私有(只能当前这个包使用)
4 //首字母大写的标识符
5 func Add(x,y int) int{
6     return x + y
7 }
 1 package main
 2 
 3 import (
 4     "fmt"
 5     "code.number.calc"
 6 )
 7 
 8 func main() {
 9     ret := calc.Add(1,2)
10     fmt.Println(ret)
11 }

  包的导入,import "包的路径"

   1、import导入语句通常放在文件开头包声明语句的下面

   2、包名从$GOPATH/scr后开始计算,使用/进行分割

  3、Go中禁止循环导入包

  4、自定义包名

    import 别名 "包路径"

十四、init()初始化函数

  在go语言程序中执行导入包语句自动触发包内部init()函数调用,init()函数没有参数也没有返回值

  1、包中init函数的执行时机全局变量==》init()函数==》main函数

  

posted @ 2020-02-16 11:42  WithSuper  阅读(181)  评论(0)    收藏  举报