gofunc function_name([params_list])([return_values_list]){
// 函数体
}
func
关键字表示定义一个函数其中,参数列表和返回值列表是可选的。有些函数无需参数,有些参数运行后并不会有任何返回值,有些函数则无需参数也无需返回值
注意
go 语言不允许函数的嵌套,因此函数应各自独立定义
gofunc fn_a(a string) string{
// do something
return a
}
// 如果连续参数具有相同的类型,我们也可以进行速记声明
func fn_b(p1, p2 string) {}
// 没有参数和返回值的函数
func fn_c(){
// do something
}
// 在别的函数调用一个函数
func main(){
rst := fn_a("123")
fmt.Println(rst)
}
// 123
go// go 中支持返回多个值
func fn_a()(string, int){
return "123", 5
}
// go 还可以在函数体定义返回值的变量
// 不建议这么使用,会降低可读性
func fn_b()(s string, i int){
var s string = "123"
var i int = 5
return
}
注意
注意
直接传递一个变量名到另一个函数中,属于值传递 值传递不会修改原变量
gofunc fn_a (num1 int, num2 int) {
// 值传递
num1 = num1 + num2
}
func main(){
var a int = 5
fn_a(a, 10)
// 5
fmt.Println(a)
}
如果想要修改原有的值,可以通过引用传递的方式实现(传递内存地址)
gofunc main(){
var a int = 5
// 传递了内存地址
fn_a(&a, 10)
// 15
fmt.Println(a)
}
func fn_a (num1 *int, num2 int) {
// 引用传递,这里直接修改了 a 内存中存储的值
*num1 = *num1 + num2
}
还可以直接定义一个全局变量,这样可以直接操作修改
go// 所有函数都能修改这个全局变量,数据存在一定的安全风险。
A int = 5
main (){
A += 10
}
go 中的函数可以直接作为一个值,类似 js 中的函数
gofunc myFunction() {
// 这里实际是创建了一个匿名函数,赋给了 fn
fn := func() {
fmt.Println("inside fn")
}
// 调用
fn()
}
匿名函数可以直接运行,所以上面的代码可以进行简化
gofunc myFunction() {
// 这里实际是创建了一个匿名函数,直接调用,注意最后的括号
func() {
fmt.Println("inside fn")
}()
}
闭包是指:
一个函数fn_a
,是另一个函数fn_b
的返回值
闭包意味着定义函数 fn_a
时访问 fn_b
范围内的值。
gofunc fn_b() func(int) int {
sum := 0
return func fn_a(v int) int {
sum += v
return sum
}
}
add := fn_b()
add(5)
// 15
fmt.Println(add(10))
解析
可以根据结果看到,sum 变量并不在 fn_a 的作用域内,但是被绑定到 fn_a 上了
好处是,这里的 sum 其实并不在外部作用域中,而是在 fn_b 中。 所以每次调用 add,都能拿到上次修改后的 sum 值
使用闭包和使用普通函数的最大区别在于:
如果是普通函数,那就是一次性买卖,函数执行完毕后就无法再更改函数中变量的值
利用闭包的特性,可以进行工厂模式相关的设计
函数中,可以使用...
省略号运算符接受零个或多个参数的函数
gofunc main() {
sum := add(1,2,3,5)
fmt.Println(sum)
}
// 注意这里的参数
func add(values ...int) int {
sum := 0
for _, v := range values {
sum += v
}
return sum
}
init是在main函数之前执行的特殊生命周期函数。 与 类似main,该init函数不接受任何参数,也不返回任何值
gopackage main
import "fmt"
// 如果有多个 init 函数,则是按照定义顺序进行执行
func inti() {
fmt.Println("初始化函数,先执行")
}
func main() {
fmt.Println("main 函数,后执行")
}
/*
$ go run main.go
初始化函数,先执行
main 函数,后执行
*/
相关信息
init函数是可选的
适用于程序可能必不可少的任何全局设置,例如建立数据库连接、获取配置文件、设置环境变量等。
defer
关键字,它可以让我们推迟一个函数的执行,直到周围的函数返回
gofunc main() {
defer fmt.Println("123")
fmt.Println("234")
}
如果有多个 defer,则会进入一个 defer stack(堆,先入后出) 即,先声明的后执行
gofunc main() {
defer fmt.Println("123")
defer fmt.Println("234")
fmt.Println("345")
fmt.Println("456")
}
相关信息
defer 语句以后进先出的方式堆叠和执行。
因此,Defer 非常有用,通常用于进行清理或错误处理。
本文作者:Silon汐冷
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!