函数
定义格式
func FuncName(/*参数列表*/) (o1 type1,o2 type2/*返回类型*/) {
// 函数体
return v1,v2 // 返回多个值
}
自定义函数
无参数无返回值函数
func MyFunc(){
a := 666
fmt.Println("a = ",a)
}
func main(){
//无参返回值函数调用:函数名()
MyFunc()
}
有参无返回值函数
func MyFunc(a int ){
fmt.Println("a = ",a)
}
func MyFunc02(a int , b int){
fmt.Print("a = %d, b = %d\n " ,a ,b )
}
func main(){
//有参返回值函数调用:函数名( 所需参数 )
MyFunc(111)
MyFunc02(555,666)
}
不定参数列表
- 不定参数,一定(只能)放在形参中最后一个元素
- 固定参数一定要传参,不定参数可根据需求灵活传参
// 类似...int 这样的类型,是不定参数类型
func MyFunc(args ...int){
for i := 0; i<len(args) ; i++ {
fmt.Printf("args[%d] = %d\n" , i, args[i])
}
for i, data := range args {
fmt.Printf("args[%d] = %d\n" , i, data)
}
}
func main(){
// 有参返回值函数调用:函数名( 所需参数 )
// 传递的实参可以是0个或多个
MyFunc(1,2,3)
}
不定参数传递
func test(args ...int){
// 全部传递
myfunc(args...);
// 只传后两个
myfunc(args[2:]...) // 从args[2]开始(包括本身),把后面所有元素传递过去
myfunc(args[:2]...) // 把从args[0]到args[2]号元素传递过去(不包括2)
}
一个返回值函数
有返回值的函数需要通过return中断函数,通过return返回
也可以提前给返回值起一个变量名,然后在函数中赋值返回
有返回值的函数,必须有return
func myfunc01() int {
return 666
}
// 给返回值起一个变量名,go语言推荐写法
func myfun02 (result int) {
return 666
}
// 或者下面这种形式 --- 常用写法
func myfunc03 (result int) {
result = 666
return
}
func main(){
var a int
a = myfunc01()
b := myfunc01()
}
多个返回值
func myfunc01() (int, int, int) {
return 1,2,3
}
// go语言官方推荐写法
func myfunc02() (a int, b int, c int) {
a, b, c = 111, 222,333
return
}
func main() {
// 函数调用
a,b,c := myfunc01()
}
有参有返回值
func MaxAndMin(a,b int) (max ,min int){
if a>b{
max = a
min = b
}else{
max = b
min = a
}
return
}
func main() {
max, min := MaxAndMin(10, 20)
}
递归函数
函数类型
在Go语言中,函数也是一种数据类型。也可以通过type给一个函数类型起名。
Go语言的“多态”实现方式。
多态:多种形态,调用同一个接口,可以实现不同的表现
适用于先有想法,后面再实现功能
type func(int , int) int // 没有函数名字,也没有{}
type FuncTyper func(int , int) int
func main(){
// 声明一个函数类型的变量,变量名叫fTest
var fTest FuncType
fTest = Add // 是变量就可以赋值
result = fTest(10, 20) // 等价于Add(10, 20)
// 也可以继续变化
fTest = minus
result = fTest(10, 5) // 等价于minus(10, 5)
}
回调函数
函数有一个参数是函数类型,这个函数就是一个回调函数。
优点:方便拓展、可以在函数体内调用暂无实现的方法。
// 实现一个可以进行四则运算的计算器
type FuncType func(int , int) int
func Calc(a, b int, fTest FuncType) (result int) {
result = fTest(a, b) // 这个函数还没有实现,(先定义调用,后实现)
return
}
func main(){
a := Calc(1, 1, Add)
}
匿名函数与闭包
func main() {
a := 10
str := "mike"
// 匿名函数,没有函数名字;此处为函数定义
f1 := func() {
// 函数内形成闭包,可以调用外面的变量
fmt.Println("a = ", a )
fmt.Println("str = ", str )
}
f1()
// 定义匿名函数,同时调用
func() {
fmt.Printf("aaa")
} () // 后面的()代表调用此匿名函数
// 匿名函数有参、有返回值、自动调用
x , y := func(i, j int) ( max, min int) {
if i>j {
max = i
min = j
}else{
max = j
min = i
}
return
}(10, 20)
}
闭包捕获外部变量的特点
闭包是以引用方式捕获外部变量,包内修改变量,包外也同步修改
闭包的特点
闭包不关心捕获了的变量和常量是否已超出作用域,只要有闭包还在使用,这些变量就会一直存在。
// 函数的返回值是一个匿名函数,返回一个函数类型
func test02() func() int {
var x int // 没有初始化,默认值为0
return func() int {
x++
return x * x
}
}
func main() {
// test02的返回值为一个匿名函数,返回一个函数类型,通过f来调用返回的匿名函数,f来调用闭包函数
f := test02()
f() // 1
f() // 4
f() // 9
f() // 16
}
延迟调用 defer
defer作用
延迟语句执行顺序,函数结束前,最后调用 defer定义的内容。
多个defer执行顺序
先defer的,后执行。先进后出。
若某一 defer 函数发生错误,其他 defer 语句正常执行。
func test(x int){
result := 100/x
return result
}
fun main() {
fmp.Println("aaaa")
fmp.Println("bbb")
test(0) // 调用一个函数,导致内存出问题
fmp.Println("ccc")
}
defer结合使用
func main() {
a := 10
b := 20
defer func() {
fmt.Printf("a= %d, b= %d\n",a,b)
} () // 打印出来结果为111,222
a = 111
b = 222
fmt.Printf("外部 a= %d, b= %d\n",a,b)
}
func main() {
a := 10
b := 20
defer func(a,b int) {
fmt.Printf("a= %d, b= %d\n",a,b)
} (a, b) // 打印出来结果为10,20,调用时,已经先传了当下的参数,后面再修改与此处无关
a = 111
b = 222
fmt.Printf("外部 a= %d, b= %d\n",a,b)
}
获取命令行参数
func main() {
list := os.Args
n := len(list)
fmt.Println("n = ",n)
for i := 0;i<n:i++{
fmt.Printf("list[%d] = %s\n",i,list[i])
}
for i,data := range list{
fmt.Printf("list[%d] = %s\n",i,data)
}
}
作用域
作用域:变量的作用范围。
局部变量
定义在{ }内的变量,只在{ }内有效。
执行到定义变量时,定义语句才会分配空间,离开作用域时,局部变量自动释放
全局变量
定义在函数外部的变量,全局变量在任何地方都能使用。
不同作用域同名变量
就近原则。
工程管理
工作区
工作区介绍
Go代码必须要放在工作区中,工作区其实就是一个对应于特定工程的目录,它应包含3个子目录:src、pkg和bin目录。
- src:以代码包形式组织并保存Go源码文件
- pkg目录:用于存放经由go install命令构建安装后的代码包(包含Go库源码文件)的".a"归档文件。
- bin目录:与pkg目录类似,在通过go install命令构建安装后,保存由Go命令源码文件生成的可执行文件。
目录src用于包含所有的源代码,是Go命令行工具的一个强制规则,而pkg和bin目录不用手动创建,Go命令行工具会自动创建。
GOPATH设置
为了能够构建这个工程,需要先把所需工程的根目录加入到环境GOPATH中。