Go语言基础进阶知识

一、函数

1、函数的定义

函数是基本的代码块,用于执行一个任务。
Go 语言最少有个 main() 函数。
你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。
函数声明告诉了编译器函数的名称,返回类型,和参数。
Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。

Go 语言函数定义格式如下:

func function_name( [parameter list] ) [return_types] {
   函数体
}
package main
import "fmt"

func main() {

	fmt.Println(add(1, 2))
}

// func 函数名 (参数,参数 ...) 函数调用后的返回值 {
//		函数体
//		return 
//}
func add(a, b int) int {
	c := a + b
	return c
}

其输出结果为

3

2、函数的声明

函数分为多种形式

  • 无参无返回值函数
  • 有一个参数的函数
  • 有两个参数的函数
  • 有一个返回值的函数
  • 有多个返回值的函数
package main
import "fmt"

func main() {

	printinfo()
	myprint("有一个参数的函数")
	cheng(1, 2)
	fmt.Println(xinxi(1, 2, "有两个参数的函数"))
	fmt.Println(swap("返回值的函数", "有多个"))
}

// 无参无返回值函数
func printinfo() {
	fmt.Println("无参无返回值函数")
}

// 有一个参数的函数
func myprint(msg string) {
	fmt.Println(msg)
}

// 有两个参数的函数
func cheng(a, b int) {
	c := a * b
	fmt.Println("有两个参数的函数:", c)
}

// 有一个返回值的函数
func xinxi(a, b int, msg string) string {
	c := a + b
	fmt.Print(c)
	return msg
}

// 有多个返回值的函数
func swap(x, y string) (string, string) {
	return y, x
}

其输出结果为

无参无返回值函数
有一个参数的函数   
有两个参数的函数: 2
3有两个参数的函数  
有多个 返回值的函数

3、形式参数和实际参数

package main

func main() {
    
	// 形参与实参要一一对应(顺序、个数、类型)
	max(1, 2)
}

// max 两个数字比大小
// 形式参数:定义函数时,用来接收外部传入数据的参数,就是形参
// 实际参数:调用函数时,传给形参的实际数据叫做实参
func max(num1, num2 int) int {
	var result int
	if num1 > num2 {
		result = num1
	} else {
		result = num2
	}
	// 一个函数定义上有返回值,那么函数中必须使用return语句
	return result
}

4、可变参数

概念:一个函数的参数类型确定,但个数不确定,就可以使用可变参数

func mydunc(arg ...int) {}
// arg ...int 告诉go这个函数收不定数量的参数,类型全是int
package main
import "fmt"

func main() {

	getSum(1, 2, 3, 5)
}

// ...可变参数
func getSum(nums ...int) {
	sum := 0
	for i := 0; i < len(nums); i++ {
		sum += nums[i]
	}

	fmt.Println("sum:", sum)
}

其输出结果为

sum: 11

注意事项:

  • 如果一个函数的参数是可变参数,同时还有其他的参数,可变参数要放在列表的最后。
  • 一个函数的参数列表中最多只能有一个可变参数

5、参数传递

按照数据的存储特点来分:

  • 值类型的数据:操作的是数据本身、int、string、bool、float64、array…
  • 引用类型的数据:操作的是数据的地址 slice、map、chan…

值传递

package main
import "fmt"

func main() {

	// 值传递
	// arr2的数据是从arr复制来的,修改arr2并不会影响arr1
	// 值传递:传递的数据的副本,修改数据,对于原始的数据没有影响
	// 定义一个数组
	arr := [4]int{1, 2, 3, 4}
	fmt.Println("原数据:", arr)
	update(arr)
	fmt.Println("调用修改后的数据:", arr)
}
func update(arr2 [4]int) {
	fmt.Println("接收前的数据:", arr2)
	arr2[0] = 100
	fmt.Println("修改后的数据:", arr2)
}

其输出结果为

原数据: [1 2 3 4]
接收前的数据: [1 2 3 4]    
修改后的数据: [100 2 3 4]  
调用修改后的数据: [1 2 3 4]

引用传递

package main

import "fmt"

func main() {

	// slice切片,可以扩容的数组,不需要定义大小
    // 引用传递相当于一个浅拷贝
	s1 := []int{1, 2, 3, 4}
	fmt.Println("原数据:", s1)
	update2(s1)
	fmt.Println("调用修改后的数据:", s1)
}
func update2(s2 []int) {
	fmt.Println("接收前的数据:", s2)
	s2[0] = 100
	fmt.Println("修改后的数据:", s2)
}

其输出结果为

原数据: [1 2 3 4]
接收前的数据: [1 2 3 4]      
修改后的数据: [100 2 3 4]    
调用修改后的数据: [100 2 3 4]

6、defer延迟函数

package main
import "fmt"

func main() {

	f("1")
	fmt.Println("2")
	defer f("3") // 会被延迟到最后执行
	fmt.Println("4")
	defer f("5")
	fmt.Println("6")
	defer f("7")
}

func f(s string) {
	fmt.Println(s)
}

其输出结果为

1
2
4
6
7
5
3

defer函数或者方法:一个函数或方法的执行被延迟了

  • 你可以在函数中添加多个defer语句,当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回,特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然容易造成资源泄露等问题。
  • 如果有很多调用defer,那么defer是采用后进先出(栈)模式。

defer穿参的时候已经传递进去了,只是最后才执行

package main
import "fmt"

// defer 关闭操作
func main() {

	a := 10
	fmt.Println("a=>", a)
	a++
	defer f(a) // 参数已经传进去了,在最后执行
	a++
	fmt.Println("end a=>", a)
}

func f(s int) {
	fmt.Println("函数里面的a=>", s)
}

其输出结果为

a=> 10
end a=> 12
函数里面的a=> 11

7、函数的数据类型

package main
import "fmt"

func main() {

    // f 如果不加括号,函数就是一个变量
	fmt.Printf("%T",f)
}

func f(s int) {
}

其输出结果为

func(int)
package main

import "fmt"

// func() 本身就是一个数据类型
func main() {

	// 定义函数类型的变量
	var f2 func(int, int)
	f2 = f1
	f2(1, 2)
	f3(f1)
}
func f1(a, b int) {
	fmt.Println(a, b)
}
func f3(f4 func(int, int)) {
	f4(3, 4)
}

其输出结果为

1 2
3 4

8、匿名函数

package main
import "fmt"

func main() {

   f1()
   f2 := f1 // 函数本送也是一个变量
   f2()

   // 匿名函数
   f3 := func() {
      fmt.Println("我是f3函数")
   }
   f3()

   func() {
      fmt.Println("我是f4函数")
   }()

   func(a, b int) {
      fmt.Print("我是f5函数")
      fmt.Println(a, b)
   }(1, 2)
}

func f1() {
   fmt.Println("我是f1函数")
}

其输出结果为

我是f1函数
我是f1函数   
我是f3函数   
我是f4函数   
我是f5函数1 2

Go语言是支持函数式编程:

  • 将匿名函数做为另外一个函数的参数,回调函数
  • 将匿名函数作为另外一个函数的返回值,可以形成闭包结构

9、回调函数

根据go语言的数据类型的特点,可以将一个函数作为另外一个函数的参数

fun1(), fun2()

将fun1函数作为fun2这个函数的参数

fun2函数:就叫做高阶函数,接收了一个函数作为参数的函数

fun1函数:就叫做回调函数,作为另外一个函数的参数

package main
import "fmt"

func main() {

	r1 := add(1, 2)
	fmt.Println(r1)

	r2 := oper(3, 4, add)
	fmt.Println(r2)

	r3 := oper(5, 3, sub)
	fmt.Println(r3)

	r4 := oper(8, 4, func(a int, b int) int {
		if b == 0 {
			fmt.Println("除数不能为0")
		}
		return a / b
	})
	fmt.Println(r4)
}

// 高阶函数
func oper(a, b int, fun func(int, int) int) int {
	r := fun(a, b)
	return r
}

func add(a, b int) int {
	return a + b
}
func sub(a, b int) int {
	return a - b
}

其输出结果为

3
7
2
2

10、闭包

package main

import "fmt"

/*
一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量
并且该外层函数的返回值就是这个内层函数。
这个内层函数和外层函数的局部变量,统称为闭包结构

局部变量的生命周期就会发生改变,正常的局部变量会随着函数的调用而创建,随着函数的结束而销毁
但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还在继续使用
*/
func main() {

	r1 := increment()
	fmt.Println(r1)
	v1 := r1()
	fmt.Println(v1)
	v2 := r1()
	fmt.Println(v2)

	//
	r2 := increment()
	v3 := r2()
	fmt.Println(v3)
	v4 := r2()
	fmt.Println(v4)
}

// 自增
func increment() func() int {
	// 局部变量
	i := 0
	// 定义一个匿名函数,给变量自增并返回
	fun := func() int {
		// 局部变量的生命周期发生了变换
		i++
		return i
	}
	return fun
}

其输出结果为

0xafe6e0
1
2
1
2
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Go语言是一种开源的编程语言,由Google公司开发并在2009年发布,其设计目标是提供一种简洁、高效、并发的编程语言,适用于构建大规模的分布式系统和网络应用。 Go语言基础包括变量、数据类型、运算符、循环、条件语句等,它具有类似C语言的语法结构,但是更加简洁易懂,容易上手。同时,Go语言还提供了丰富的标准库,包括网络、并发、文件操作等功能,可以满足日常开发的基本需求。 在Go语言进阶部分,学习者可以深入了解Go语言的并发编程模型。Go语言通过goroutine和channel两个关键特性来实现并发编程,goroutine类似于线程,但是比线程更加轻量级和高效,channel则是用于goroutine之间的通信。这种并发编程模型的设计使得开发者可以方便地编写高效的并发程序,从而提升系统的性能和可伸缩性。 就业方面,掌握Go语言可以为就业创造更多的机会。随着云计算和大数据技术的不断发展,对于高性能、分布式、高并发的编程语言的需求也越来越大。而Go语言作为一种专注于构建高性能网络服务的语言,正在受到越来越多公司的青睐。因此,具备熟练的Go语言技能,可以有更多的就业选择,并且在薪资待遇方面也有一定的优势。 总结来说,Go语言作为一种简洁、高效、并发的编程语言,具有良好的学习曲线和广泛的应用领域。通过深入学习和掌握,可以在基础进阶和就业方面获得全面的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_咸蛋.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值