golang学习笔记(四)

本文是关于Go语言的学习笔记,介绍了Go的main()函数作为程序入口,强调了Go通过package组织程序并检查引入包的有效性,不同于C/C++。详细讲解了Go函数的定义与命名规则,特别是函数支持多个返回值的功能。此外,还探讨了Go的匿名函数(闭包)及其对外部变量的影响,以及defer关键字的使用,包括其在资源管理中的作用和执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         go语言中一定有一个main()函数,作为程序的入口,这个跟C/C++是一样的,有main()函数的package是main package,go语言通过package(包)来组织程序,跟C/C++中引用头文件不同,要清晰很多,C/C++在编译时不会检测引入的头文件是否有用,而引入过多的头文件会导致编译起来特别慢。go编译时会检查引入的包是否用了,如果没有用会报错,这一点就非常好的。

        go中的函数用关键字func开头,形式是

         func 函数名(参数列表) 返回值类型 {

                 //todo

        }

        函数名根据约定,函数名首字母大写即为public,小写即为private。其实我们通过调用go提供包的函数时可以看出,我们调用的函数首字母都是大写的,比如(fmt.Println)。

        go语言中的函数支持多个返回值,这个是C/C++中没有的,在写C/C++程序的时候,经常遇到要返回多个数值的时候,因为不支持,只能通过引用参数带出函数中的计算数值,感觉不是特别方便。

示例代码如下:

package main

import (
	"fmt"
	"strconv"
)

//这种是值传递,将实际参数复制一份传递到函数中,在函数中如果对参数进行修改,将不会影响到实际参数
func addVal1(v1, v2 int, str string) (int, string) {
	r1 := v1 + v2
	r2 := str + "_" + strconv.Itoa(r1)
	return r1, r2 //返回一个int和一个string
}

func addVal2(v1, v2 int, str string) (r1 int, r2 string) { //可以给返回值起一个变量名,go推荐写法
	r1 = v1 + v2
	r2 = str + "_" + strconv.Itoa(r1)
	return //如果有返回值必须在函数内部添加return
}

//不定参数类型,...type
func addVal3(str string, args ...int) (int, string) { //不定参数个数可以是0或者多个
	var r1 int
	for i := 0; i < len(args); i++ { //len(args)获取用户传递参数个数
		r1 += args[i]
	}
	r2 := str + "_" + strconv.Itoa(r1)
	return r1, r2 //
	/*
		这种方式也可以
		for i, data := range args{

		}*/
}

//函数递归实现累加
func sumVal(i int) int {
	if i == 1 {
		return i
	}
	return i + sumVal(i-1)
}

func main() {
	r1, r2 := addVal2(100, 1, "addVal1")
	fmt.Println(r2, r1)

	r3, r4 := addVal2(100, 1, "addVal2")
	fmt.Println(r4, r3)

	r5, r6 := addVal3("addVal2", 100, 1, 10)
	fmt.Println(r6, r5)

	sum := sumVal(10)
	fmt.Println(sum)
}

       

        go语言支持匿名函数,可以叫做闭包,匿名函数是一个“内联”语句或者表达式,可以直接使用函数内的变量(以引用方式捕获外部变量,可以修改外部变量)。

package main

import "fmt"

func test() func() int { //返回值是一个无参数返回值为int的函数
	i := 0

	return func() int {
		i++
		return i
	}
}

func main() {

	i := 100
	str := "hello"
	//匿名函数 后面加()直接调用
	func() { //以引用方式捕获外部变量,可以修改
		i = 55
		fmt.Println(str, i)
	}()

	f1 := func() { //:=自动推导类型 f1 为函数类型变量
		i = 66
		fmt.Println(str, i)
	}
	//调用
	f1()
	fmt.Println(str, i)
	/* f 是一个函数 其中变量i=0
	test函数返回值是一个匿名函数
	*/

	f := test()
	/*
		通过f来调用返回的匿名函数,闭包不关心捕获的的变量已经超出作区域,
		只要还在使用它,这些变量就一直存在,所以i初始值0 每次调用+1
	*/
	fmt.Println(f()) //1
	fmt.Println(f()) //2
	fmt.Println(f()) //3
	fmt.Println(f()) //4
	fmt.Println(f()) //5

	f = test()
	fmt.Println(f()) //1
	fmt.Println(f()) //2
}

        defer关键字作用是后面跟随的语句延迟调用,会在defer归属的函数结束之前调用。它一般用于释放某些已经申请的资源(比如互斥锁,或者打开的文件)。如果是多个defer遵循LIFO(先进后出)出栈的方式处理。哪怕函数执行过程中或者defer语句出现错误,后面执行的defer的语句依然会被执行。

示例代码如下:

package main

import "fmt"

func main() {
	defer fmt.Println("first defer")
	defer fmt.Println("second defer")

	var x int
	r := 100 / x

	defer fmt.Println("last defer", r)

}
package main

import "fmt"

func main() {
	x := 1
	y := 100

	defer func(a, b int) {
		fmt.Printf("x = %d y = %d\n", a, b)
	}(x, y) //代表调用此匿名函数,并且把参数传递进去了,只是没有调用

	x = 2
	y = 200
	fmt.Printf("x = %d y = %d\n", x, y)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值