Go 函数
本文最后更新于:13 天前
1 函数定义
函数是组织好的,可重复使用的,用于执行指定任务的代码块,本文介绍go语言函数的相关内容
Go 语言支持: 函数 ,匿名函数,闭包
Go 语言中定义函数使用func 关键字
func 函数名(函数参数)函数返回值 {
函数体
}
- 函数名: 由 字母 数字 下划线组成 但是函数名的第一个字母不能是数字,在同一个包内,函数名称,不能重名
- 函数参数:参数由参数变量和参数变量的类型组成,多个参数可以使用逗号分隔
- 函数返回值:返回值由返回值变量和其变量类型组成,也可以只写返回值,多个返回值必须用()包裹,并且用逗号,分隔
- 函数体: 实现指功能的代码块
2 函数使用案例
package main
import (
"fmt"
)
func sumFunc(x int ,y int) int {
sum := x + y
return sum
}
func subFunc(x,y int ) int { //当数据类型是相同的情况下, 可以最后只写一个
sub := x - y
return sub
}
func main() {
sum1 := sumFunc(1, 3)
fmt.Println(sum1)
sub1 := subFunc(3,1)
fmt.Println(sub1)
}
3 函数可变参数
通常可变参数要写在最后一个参数,Go中使用在参数后面加… 来标识
func sumFunc1(x ...int) { //可变参数: 可以用三个点 ... 来接收多个值
fmt.Printf("%v,%T\n",x,x)
}
func sumFunc2(x ...int) int { //可变参数: 可以用三个点 ... 来接收多个值
sum := 0
for _,v := range x {
sum += v
}
return sum
}
func calc1(x int,y ...int ) int { //传递可变长参数,可变长参数放在关键词后面
sum := 0
for _,v := range y {
sum += v
}
return sum
}
sumFunc1(1,3,35,6)
sum2 := sumFunc2(1,100,100,99)
fmt.Println(sum2)
sumCalc1 := calc1(3,2,100,100,88)
fmt.Println(sumCalc1)
4 函数多个返回值
package main
import "fmt"
func calc(x, y int) (int ,int ) {
sum := x + y
sub := x - y
return sum,sub
}
func calc1(x ,y int ) (sum int,sub int) {
sum = x + y
sub = x - y
return sum ,sub
}
func main() {
sumRes,subRes := calc(3,1)
fmt.Println(sumRes)
fmt.Println(subRes)
sum1,sub1 := calc1(10,3)
fmt.Println(sum1)
fmt.Println(sub1)
}
5 函数的参数和返回值是可选的
函数的参数和返回值都是可选的。下面我们实现一个参数和返回值都没有的函数
func say() {
fmt.Println("test")
}
6 把排序封装成方法
实现整形的升序和降序顺序排列,string类型按照字符的首字母进行排序,首字母相同,继续往后一次对比
6.1 int类型升序
package main
import "fmt"
func sortIntAsc(slice []int) []int {
for i :=0;i< len(slice);i++ {
for j := i +1 ;j<len(slice) ;j++ {
if slice[i] > slice[j] {
tmp := slice[i]
slice[i] = slice[j]
slice[j] = tmp
}
}
}
return slice
}
func main() {
slice1 := []int{12,23,34,1,25,100,444,2}
sortSlice := sortIntAsc(slice1)
fmt.Println(sortSlice)
}
6.2 int类型降序
func sortIntDes(slice []int) []int {
for i :=0;i< len(slice);i++ {
for j := i +1 ;j<len(slice) ;j++ {
if slice[i] < slice[j] {
tmp := slice[i]
slice[i] = slice[j]
slice[j] = tmp
}
}
}
return slice
}
6.3 map对象 按照key进行排序
package main
import (
"fmt"
"sort"
)
func mapSort(m map[string]string) string {
var sliceKey []string
for k,_ := range m {
sliceKey = append(sliceKey, k)
}
sort.Strings(sliceKey)
var str string
for _,v := range sliceKey {
str += fmt.Sprintf("%v=>%v |" ,v,m[v])
}
return str
}
func main() {
var map1 = map[string]string {
"username": "bds",
"age": "19",
"worker": "linux",
"sex": "男",
"aaa": "aaa",
}
str1 := mapSort(map1)
fmt.Println(str1)
}
//age=>19 |sex=>男 |username=>bds |worker=>linux |
7 函数变量作用域
全局变量: 全局变量是定义在函数外部的变量,他在程序整个运行周期内都有效
局部变量: 局部变量是定义在函数内部的变量, 函数定义的变量无法在函数外使用
package main
import "fmt"
var a = "全局变量"
func run() {
var b = "局部变量"
fmt.Println("run方法a: ",a)
fmt.Println("run方法b: ",b)
}
func main() {
run()
fmt.Println("main方法a: ",a)
// fmt.Println("main方法b: ",b) //undefine:b 报错
//i 是局部变量,只能在for方法内中使用
for i := 0;i < 10 ;i++ {
fmt.Println(i)
}
//本作用域中相当于全局变量
var flag = true
if flag {
fmt.Println("true")
}
// 局部作用域 ,局部变量
if flag := true ;flag {
fmt.Println("true")
}
fmt.Println(flag) //undefine: flag
}
8 自定义函数类型
我们可以使用type关键字来定一个函数类型,具体格式如下:
type calc func(int,init) int
上面语句定义了一个calc 类型,他是一个函数类型, 这种函数接收俩个int类型的参数并且返回一个int类型的返回值
简单来说,凡是满足这个条件的函数都是calc类型的函数,如果是不满足条件强行赋值是会报错的
package main
import "fmt"
//自定义方法类型
type calc func(int,int) int
//自定义整形类型
type myInt int
func add(x,y int) int {
return x + y
}
func sub(x,y int) int {
return x - y
}
func test() {
fmt.Println("test")
}
func main() {
var c calc
c = add
fmt.Printf("c的类型: %T\n",c ) //c的类型: main.calc 这里是我们自定义类型
f := sub
fmt.Printf("f的类型:%T\n",f) //f的类型:func(int, int) int 这里是类型推导
var a = 10
var b myInt = 10
fmt.Printf("%v,%T\n",a,a) //10,int
fmt.Printf("%v,%T\n",b,b) //10,main.myInt
//因为b重新定义了myInt,myInt虽然是始于int定义的,但是还是属于俩个类型,不能相加
//fmt.Println(a+b) //invalid operation: a + b (mismatched types int and myInt)
fmt.Println(a+int(b)) //20
}
9 函数作为另一个函数的参数
9.1 函数作为参数
package main
import (
"fmt"
)
type calcType func(int,int) int
func add(x,y int) int {
return x + y
}
func sub(x,y int ) int {
return x - y
}
func do(a,b int,cb calcType) int {
return cb(a,b)
}
func main() {
var c = do
doValue := c(1,3,add)
fmt.Println(doValue)
//用匿名函数直接作为参数进行传参
cValue := c(1,3,func(x,y int) int {
return x * y
})
}
9.2 函数作为返回值
package main
import "fmt"
type calcType func(int,int) int
func add(x,y int) int {
return x + y
}
func sub(x,y int) int {
return x - y
}
func do(cmd string) calcType {
switch cmd {
case "+":
return add
case "-":
return sub
case "*":
return func(x,y int ) int {
return x * y
}
default:
return nil
}
}
func main() {
var c = do("*")
fmt.Println(c(2,3))
}
10 匿名函数和闭包
10.1 匿名函数使用
函数当然还可以作为返回值,但是在Go语言中函数内部不能在像之前那样定义函数了,只能是定义匿名函数,匿名函数就没有函数名字的函数,匿名函数的定义格式如下:
func(参数)(返回值) {
函数体
}
匿名函数因为没有函数名字,所以没办法像普通函数那样被调用,所以匿名函数需要保存到某个变量或者作为立即执行函数
package main
import "fmt"
func main() {
//通过变量保存匿名函数
var add = func(x,y int) int {
return x + y
}
fmt.Println(add(10,20))
//自执行函数,匿名函数定义后面加()直接执行
func(x,y int) {
fmt.Println(x * y)
}(10,20)
}
10.2 闭包使用
闭包可以理解成 定义在一个函数内部的函数,在本质上,闭包是将函数内部和函数外部连接起来的桥梁,或说是函数和其引用环境的组合体,首先我们先看一个例子
- 闭包就是指有权访问另外一个函数作用域中的变量的函数
- 创建闭包的常见方式就是在一个函数内部创建另外一个函数,通过另外一个函数访问这个函数的局部变量
注意: 由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存,过度使用闭包会导致性能下降。
全局变量
- 常驻内存
- 污染全局
局部变量的特点
- 非偿住内存
- 不污染全局
闭包:
- 可以让一个变量常驻内存
- 可以让一个变量不污染全局
package main
import "fmt"
func addr(y int) (s int) {
var i = 10 //常驻内存,不污染全局
var fn1 = func(y int) int {
i += y
return i
}(y)
s = fn1
return s
}
func main() {
var fn = addr(3)
fmt.Println(fn)
fmt.Println(fn)
fmt.Println(fn)
}
/*
13
13
13
*/
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!