package main
import "fmt"
func main(){
//功能: 10 + 20
var num1 int = 10
var num2 int = 20
var sum int = 0
sum += num1
sum += num2
fmt.Println(sum)
}
为什么使用函数
提高代码的复用性,减少代码冗余, 代码维护性也提高了
函数的定义
为完成摸一个功能的程序指令(语句)的集合,称为函数
基本语法
func 函数名(形参列表)(返回值类型列表){
执行语句..
return + 返回值列表
}
package main
import "fmt"
func addSum(num1 int,num2 int) (int){ //如果返回值类型就一个的话,那么()可以省略
return num1 + num2
}
func main(){
//功能: 10 + 20
var sum int = addSum(10,50)
fmt.Println(sum)
}
函数的一些注意点
go语言中函数是并列的,所以你无论写在main函数的前面还是后面都是可以调用到函数
命名规则
函数名
- 首字母不能是数字
- 首字母大写该函数可以被本报文件和其他文件使用(类似于public)
- 首字母小写只能被本包文件使用,其他文件不能使用(类似于private)
形参列表
- 形参列表: 个数: 可以是一个参数,可以是n个参数, 可以是0个参数
- 参数列表: 作用: 接收外来的数据
- 实际参数: 实际传入的数据:
返回值类型列表
- 可以返回0个数据
- 可以返回1个数据
- 可以返回多个数据
返回0个数据
package main
import "fmt"
func addSum(num1 int,num2 int){
fmt.Println(num1 + num2)
}
func main(){
addSum(10,50)
}
返回1个数据
func addSum(num1 int,num2 int) int{ //如果返回值只有一个,那么返回值的左右()可以省略不写
return num1 + num2
}
返回多个(俩个)数据
package main
import "fmt"
func calSum(num1 int,num2 int) (int ,int) {
var sum1 int = num1 + num2
var sum2 int = num1 - num2
return sum1,sum2
}
func main(){
//功能: 10 + 20
// var sum int = addSum(10,50)
// fmt.Println(sum)
sum,jian := calSum(50,10)
fmt.Println(sum,jian)
}
如果你想要忽略其中一个返回值
package main
import "fmt"
func calSum(num1 int,num2 int) (int ,int) {
var sum1 int = num1 + num2
var sum2 int = num1 - num2
return sum1,sum2
}
func main(){
sum,_ := calSum(50,10) //_:忽略
fmt.Println(sum)
}
如果只有一个参数接俩个返回(错误)
package main
import "fmt"
func calSum(num1 int,num2 int) (int ,int) {
var sum1 int = num1 + num2
var sum2 int = num1 - num2
return sum1,sum2
}
func main(){
sum := calSum(50,10) //一个参数接俩个返回
fmt.Println(sum)
}
内存注意点
package main
import "fmt"
func main(){
var num1 int = 10
var num2 int = 20
fmt.Printf("交换前num1:%d,num2:%d\n",num1,num2)
jiaohuan(num1,num2)
fmt.Printf("交换后num1:%d,num2:%d\n",num1,num2)
}
//交换俩个数
func jiaohuan (num1 int,num2 int){
var t int
t = num1
num1 = num2
num2 = t
}
实际上
jiaohuan(函数)
执行结束后,内存会销毁jiaohuan栈帧(栈空间),实际上将形参进行了交换,跟在外界的俩个数没有任何关系
内存分析
- 栈
- 存放基本数据类型
- 堆
- 存放引用/复杂数据类型
- 代码区
- 存放代码本身
若你执意要改变它们本身
package main
import "fmt"
func main(){
var num1 int = 10
var num2 int = 20
fmt.Printf("交换前num1:%d,num2:%d\n",num1,num2)
num1,num2 = jiaohuan(num1,num2) //将返回结果赋值给num1和num2
fmt.Printf("交换后num1:%d,num2:%d\n",num1,num2)
}
//交换俩个数
func jiaohuan (num1 int,num2 int) (int,int){ //添加返回值
var t int
t = num1
num1 = num2
num2 = t
return num1,num2
}
Go语言不支持重载
函数名相同,形参列表不同
package main
import "fmt"
func main(){
var num1 int = 10
var num2 int = 20
fmt.Printf("交换前num1:%d,num2:%d\n",num1,num2)
num1,num2 = jiaohuan(num1,num2)
fmt.Printf("交换后num1:%d,num2:%d\n",num1,num2)
}
//交换俩个数
func jiaohuan (num1 int,num2 int) (int,int){
var t int
t = num1
num1 = num2
num2 = t
return num1,num2
}
func jiaohuan (num1 int) (int,int){
var num2 int = num1
return num1,num2
}
declared
: 定义,声明
re
: 在编程语言中是重复反复的意思
Golang中支持可变参数(如果你希望函数带有可变参数)
package main
//定义一个函数,函数的参数为: 可变参数 ... 参数的数量可变
//args...int: 可以传入任意多个数量的int类型的数据 传入0~n个实参
func test(args...int){}
func main(){
test()
test(1,2,3,4,5)
}
基本数据类型和数组默认都是值传递的,即进行拷贝。不会影响到原来的值
package main
import "fmt"
func test(num int){
num = 30
fmt.Println("test--",num)
}
func main(){
var num int = 10
test(num)
fmt.Println("main--",num)
}
在内存中, test栈帧中的值只是将test里的num值进行了改变,而main中的num并没有改变(改的是形参)
以值传递的方式的数据类型,如果希望在函数的变量能修改函数外的变量,可以传递变量的地址&
,函数内以指针的方式操作变量,从效果来看类似引用传递
package main
import "fmt"
//参数的类型是指针
func test(num *int){
*num = 30
fmt.Println("test--",*num)
}
func main(){
var num int = 10
test(&num)
fmt.Println("main--",num)
}
在Go中函数也是一种数据类型,可以传递给一个变量,则该变量就是一个函数类型的变量,通过该变量可以对函数调用
package main
import "fmt"
//参数的类型是指针
func test(num int){
fmt.Println(num)
}
func main(){
a := test
fmt.Printf("a对应的类型:%T,test函数对象的类型: %T",a,test)//a对应的类型:func(int),test函数对象的类型: func(int)
}
对函数进行调用
package main
import "fmt"
//参数的类型是指针
func test(num int){
fmt.Println(num)
}
func main(){
a := test
fmt.Printf("a对应的类型:%T,test函数对象的类型: %T\n",a,test)//a对应的类型:func(int),test函数对象的类型: func(int)
a(10)//等价于test(10)
}
函数既然是一种数据类型,因此在Go中,函数可以作为形参,并且调用(把函数本身当作一种数据类型)
package main
import "fmt"
//参数的类型是指针
func test(num int){
fmt.Println(num)
}
func test02(num1 int,testFunc func(int)){
fmt.Println("test--",testFunc)
}
func main(){
a := test
fmt.Printf("%T,%T\n",a,test)
test02(10,a)
}
为简化数据类型定义,Go支持自定义数据类型
基本语法: type 自定义数据类型名 数据类型
package main
import "fmt"
func main(){
type myInt int
var i myInt = 10
fmt.Printf("%T\n",i)
}
package main
import "fmt"
func main(){
type myInt int
var i myInt = 10
fmt.Printf("%T\n",i)
var a int = 20
a = i //虽然是别名,但是在go中编译识别的时候还是认为myInt和int是一个数据类型
}
要让运行通过将myInt
转成int
(强转)
package main
import "fmt"
func main(){
type myInt int
var i myInt = 10
fmt.Printf("%T\n",i)
var a int = 20
a = int(i)//虽然是别名,但是在go中编译识别的时候还是认为myInt和int是一个数据类型
}
支持函数起别名
type mySun func(int,int)int
–>这是mySum
就等价一个哈桑农户类型func(int,int) int
package main
import "fmt"
func test(num int){}
type myFunc func(int)
func test02(num int,test myFunc){
fmt.Println("test--",test)
}
func main(){
a := test
test02(10,a)
}
支持对函数返回值命名
package main
import "fmt"
func test(num1 int,num2 int)(sum int, sub int){
sum = num1 + num2
sub = num1 - num2
return
}
func main(){
sum,sub := test(10,5)
fmt.Println(sum,sub)
}
可以说是
func test(num1 int,num2 int)(int,int){
sum := num1 + num2
sub := num1 - num2
return sum,sub
}
的升级版了