本节重点
- goland设置git终端
- go的install命令
- 内存逃逸
- 接口与类型断言
- 多态
- return、exit、Goexit之间的区别
内容详解
goland设置git终端
setting-->tools-->terminal-->shell path设置为你下载git的文件夹bin目录下的bash.exe
go常用命令(build/run/install/env)
go env:查看go的环境变量。
go install:编译生成的exe文件无法在别的目录运行,如何解决这个问题呢?使用go install命令将exe文件保存到GOPATH下的bin目录中,即GOBIN中,将GOBIN配置进系统变量就可以在任意目录下运行这个exe文件了。
内存逃逸
go语言声明一个变量,会自动将其放到堆上或者栈上,如果是临时变量就会放到栈上,如果不能随便释放的变量就会放到堆上。这个分配过程在编译的时候就确定了。
看下面这个程序
func main() {
fmt.Println(*testPtr())
}
func testPtr() *string {
city := "上海"
ptr := &city
return ptr
}
这个程序能否正常打印city?答案是可以的。如果是c语言,当函数结束时,内存就会被销毁,其city变量也会被清空。而go语言则不会,因为go把city变量存放在了堆空间中,堆空间中的变量不会随着函数的结束而销毁。
那么如何更清晰的看到它是在堆上还是栈上?通过编译器查看。
$ go build -o test.exe --gcflags "-m -m -l" main.go
也可以用重定向打印到文件中:
$ go build -o test.exe --gcflags "-m -m -l" main.go >1.txt 2>&1
然后用greap更清楚的查看:
$ grep -E "name|city" 1.txt --color
可以看到city逃逸了而name没有逃逸。
接口与类型断言
array := make([]interface{}, 3)
array[0] = 1
array[1] = "Hello"
array[2] = true
for _, value := range array {
switch v := value.(type) {
case int:
fmt.Printf("当前类型为int,内容为:%d\n", v)
case string:
fmt.Printf("当前类型为string,内容为:%s\n", v)
case bool:
fmt.Printf("当前类型为bool,内容为:%v\n", v)
default:
fmt.Println("不识别当前类型")
}
多态
Go语言的多态的实现不需要父子类关系,只需要实现同一个接口的所有方法即可。
下面的程序中,Student和Teacher都实现了People接口,因此可以声明一个People接口的变量,指向Student和Teacher的对象。
type People interface {
printAge()
}
type Student struct {
age int
}
func (s *Student) printAge() {
fmt.Println("Student age is :", s.age)
}
type Teacher struct {
age int
}
func (t *Teacher) printAge() {
fmt.Println("Teacher age is :", t.age)
}
func doPrint(p People) {
p.printAge()
}
func main() {
var people People
student := Student{
11,
}
teacher := Teacher{
25,
}
people = &student
people.printAge()
people = &teacher
people.printAge()
doPrint(&student)
doPrint(&teacher)
}
return、exit、Goexit之间的区别
- return :退出当前函数
- exit :退出当前进程
- Goexit :退出当前go程
go func(){
go func() {
func(){
fmt.Println("这是子go程内部的函数")
//return
//os.Exit(-1)
//runtime.Goexit()
}()
fmt.Println("子go程结束")
}()
time.Sleep(2*time.Second)
fmt.Println("这是最外层go程")
}()
fmt.Println("这是主go程")
time.Sleep(3*time.Second)
fmt.Println("OVER")