var name string
func main() {
name = "Nick"
fmt.Println(name)
f1()
}
func f1() {
name := "Dawn"
fmt.Println(name)
f2()
}
func f2() {
fmt.Println(name)
}
输出:
Nick
Dawn
Nick
作用域栗子
匿名函数 & 闭包
匿名函数
匿名函数是由一个不带函数名的函数声明和函数体组成。
package main
func main() {
f := func(x, y int) int {
return x + y
}
f(1,1)
ch := make(chan int)
func (ch chan int) {
ch <- 9
}(ch)
}
闭包
闭包是一个函数和与其相关的引用环境组合而成的实体。
函数可以存储到变量中作为参数传递给其它函数,能够被函数动态的创建和返回。
func Adder() func(int) int {
var x int
return func(d int) int {
x += d
return x
}
}
f := Adder()
fmt.Println(f(1)) //1
fmt.Println(f(10)) //11
fmt.Println(f(100)) //111
package main
import (
"fmt"
"strings"
)
func makeSuffix(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
func main() {
f1 := makeSuffix(".png")
fmt.Println(f1("name1")) //name1.png
fmt.Println(f1("name2")) //name2.png
f2 := makeSuffix(".jpg")
fmt.Println(f2("name1")) //name1.jpg
fmt.Println(f2("name2")) //name2.jpg
}
闭包栗子二
值传递 & 引用传递
无论是值传递,还是引用传递,传递给函数的都是变量的副本;
值传递是值的拷贝,引用传递是地址的拷贝;
一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。
map、slice、chan、指针、interface默认以引用的方式传递。
new 内置函数 用来分配内存,主要用来分配值类型,比如int、struct,返回的是指针;
make 内置函数 用来分配内存,主要用来分配引用类型,比如chan、map、slice。
程序初始化与执行过程
程序的初始化和执行都起始于main包。
如果main包还导入了其它的包,那么就会在编译时将它们依次导入。
有时一个包会被多个包同时导入,那么它只会被导入一次(例如很多包可能都会用到fmt包,但它只会被导入一次,因为没有必要导入多次)。
当一个包被导入时,如果该包还导入了其它的包,那么会先将其它包导入进来,然后再对这些包中的包级常量和变量进行初始化,接着执行init函数(如果有的话),依次类推。
等所有被导入的包都加载完毕了,就会开始对main包中的包级常量和变量进行初始化,然后执行main包中的init函数(如果存在的话),最后执行main函数。
指针类型(&*)
普通类型,变量存的就是值,也叫值类型;
指针类型,变量存的是一个地址,这个地址存的才是值。
变量是一种占位符,用于引用计算机内存地址;
Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。
获取指针类型所指向的值,使用:*。
一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。
申明如下:
var age *int //指向整型
var height *float32 //指向浮点型
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
栗子
package main
import "fmt"
func main() {
var ptr *int
num := 100
ptr = &num
fmt.Println(ptr) //0xc42000e1f8
fmt.Println(*ptr) //100
*ptr = 200
fmt.Println(num) //200
}
package main
import "fmt"
func change(num *int) {
fmt.Println(num) //0xc42000e1f8
fmt.Println(*num) //100
*num = 1000
fmt.Println(num) //0xc42000e1f8
fmt.Println(*num) //1000
}
func main() {
num := 100
fmt.Println(&num) //0xc42000e1f8
change(&num)
fmt.Println(&num) //0xc42000e1f8
fmt.Println(num) //1000
}