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函数


浙公网安备 33010602011771号