go安装
在https://golang.google.cn/dl/下载对应的版本之后解压要想要的文件夹
配置环境变量:
GOROOT
: go编译器所在的文件夹GOPATH
: go三方src所在的文件夹,如果不用go mod的话,所有的项目都要在GOPATH的src目录下编程.GOPROXY
: go的代理,国内一般设置为https://goproxy.io,direct"
将GOPATH
的bin
文件夹加入PATH
环境,以便于能够通过命令行访问。
linux:的profile文件配置如下Windows配置类似。1
2
3
4
5# golang
export GOROOT=/work/soft/go
export GOPATH=/work/soft/dev/gopath
export GOPROXY=https://goproxy.io,direct
export PATH=$PATH:$GOROOT/bin
go get 无法使用问题解决办法
使用第三方包gopm
设置代理。windows需要设置相应的环境变量
1 | go env -w GO111MODULE=on |
匿名函数
普通函数变量
1
2
3anon := func(a int,b int)int{
return a + b
}anon是一个函数变量。
函数返回函数
1
2
3
4
5
6
7annof := func() func(int,int) int{
return func(a1 int, b1 int) int{
return a1 + b1
}
}
anon2 := annof()
}anon2 也是一个匿名函数,该函数是返回一个函数。
自启动。并且传参
1
2
3
4
5
6anon3 := func(param string)func(int,int) int {
fmt.Println("param",param)
return func(a1 int,b1 int) int{
return a1 + b1
}
}("Hello World!")函数别名
1
2
3
4
5
6type returnFunctionType func(int,int) int
anon4 := func() returnFunctionType {
return func(a1 int, b1 int) int{
return a1 + b1
}
}()调用函数
1
2
3
4fmt.Println("anon func =",anon(1,2))
fmt.Println("anon func2 = ",anon2(1,2))
fmt.Println("anon func3 = ",anon3(1,2))
fmt.Println("anon func4 = ",anon4(1,2))调用结果
1
2
3
4
5param Hello World!
anon func = 3
anon func2 = 3
anon func3 = 3
anon func4 = 3
闭包
- 累加器
1
2
3
4
5
6
7
8func addUper() func(int)int {
base := 10
return func(n1 int) int{
res := base + n1
base ++
return res
}
}
说明 改函数不依赖外部的数据实现累加。返回的func(int)int
中含有一个base变量。该变量会自增。不会因为被调用而初始化。
- 图片后缀
1
2
3
4
5
6
7
8
9func suffixImage(s string) func(string)string {
return func(path string) string {
if strings.HasSuffix(path,s) {
return path
}else{
return path + s
}
}
}
说明 该函数返回一个闭包。能够识别是否拥有对应的后缀。没有就自己添加。
闭包总结
闭包等价于函数,但是该函数和普通的函数不一样的是,函数内部有一个不受外部影响而变化的变量。外部调用该函数时并不会重置该闭包内的数据。
接口和类型断言
1、接口
接口作为一种规范。接口是对继承的补充,并且通过接口可以实现上转型和下转型。golang的所有变量类型都是实现空接口,意味着可以将golang的各种类型上转成接口,然后再通过类型断言下转成具体类型。golang的空接口类似于java中的Object
1.1 接口的声明
1 | type Usb interface { |
和java的接口一样,接口是作为一种规范,一个模板。没有具体的实现方式
1.2 接口的实现
和java不同的是,golang的接口实现不用显示的绑定,完全松耦合。只要一个类型或者变量实现了某个接口中定义的函数。即函数一样,就可以说该变量或者类型实现了该接口
1 | type Phone struct{ |
类型Phone
和Camera
实现了Usb
接口。但是看起来这两个类型没有和Usb
这个接口联系起来。根本没有任何的绑定,java至少有implement
来说明绑定的接口。唯一能和接口联系上的就是这两个类型都有Start()
和Stop()
函数。通过函数一样来绑定接口。
1.3 接口的使用
接口可以赋值,用具体实现类来赋值。这个和java的接口一致。可以使用接口类型来承接具体的类型
1 | var usb Usb = Phone{name: "apple"} |
usb的接口变量可以接收具体的实现类,接口会隐藏掉具体实现类中其它的特征,Phone
中的Call()
函数被隐藏了。
2、类型断言
类型断言类似于下转型,通过类型断言可以将接口下转成具体的实现类。实现接口的类型和断言的类型一致才会转换成功。value,ok := i.(Phone)
转换失败由第二个参数接收,转换成功由第一个参数接收转换后的具体实现类。
2.1 类型断言的使用(一)
1 | type Computer struct{ |
computer
的Working(usb Usb)
函数使用了,usb接口类型,如果传进来的实现类是Phone
就调用Call()方法。如果是Camera
就调用Photography()
1 | var usbArr [3]Usb = [3]Usb{ |
输出
1 | 手机开始工作。。。。 |
2.2 类型断言的使用(二)
使用一个类型判断函数
1 | func TypeJudge(item... interface{}){ |
调用函数
1 | TypeJudge(1,"stringvalue",1.1,Phone{"phone"},Camera{"camera"},computer) |
控制台输出
1 | 第0参数 int 类型,值为:1 |
panic
捕获函数panic的defer必须在调用函数之前才能捕获。
1 | func TestPanic() { |
测试
当一个go文件以_test.go作为后缀的时候不会参与build.使用go test
命令会执行里面的测试函数
- 测试函数:以Test开始的函数,入参为
(t *testing.T)
- 基准测试:以Benchmark做前缀的函数,入参为
(t *testing.B)
- 示例函数:以Example做前缀的函数。入参为空。需要有注释//Output:作为输出结果。
例子
命令行执行:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 测试函数
func TestHelloWorld(t *testing.T) {
fmt.Println("Function Test Hello world")
}
func BenchmarkHello(t *testing.B) {
fmt.Println("Benchmark Test Hello")
}
func ExampleHello() {
//fmt.Println(false)
fmt.Println(true)
// Output:
// true
// false
}go test
就会执行测试函数。
添加-bench参数,启动bench测试。go test -bench=.
golang学习路线
golang基础、进阶、大师。