当前位置: 首页 > news >正文

网站开发费用报价单/seo课程培训视频

网站开发费用报价单,seo课程培训视频,深圳之窗,建站公司哪家好都选万维科技一、函数定义 1.1、函数的定义 Go语言中定义函数使用func关键字,具体格式如下:func 函数名(参数 type)(返回值type){ 函数体 } 函数名:由字母、数字、下划线组成。但函数名的第一个字母不能是数字。在同一个包内,函数名也称不…

一、函数定义

1.1、函数的定义

Go语言中定义函数使用func关键字,具体格式如下:
func 函数名(参数 type)(返回值type){
    函数体
}

  • 函数名:由字母、数字、下划线组成。但函数名的第一个字母不能是数字。在同一个包内,函数名也称不能重名(包的概念详见后文)。
  • 参数:参数由参数变量和参数变量的类型组成,多个参数之间使用,分隔。
  • 返回值:返回值由返回值变量和其变量类型组成,也可以只写返回值的类型,多个返回值必须用()包裹,并用,分隔。
  • 函数体:实现指定功能的代码块。

1.2、函数的使用(汇总)

// 定义一个求和函数(有参数),有return返回值时(需要给返回值定义一个类型)
func s1(x int, y int) int {return x + y
}// 定义一个求和函数(有参数),没有return返回值时
func s2(x int, y int) {fmt.Println(x + y)
}// 定义一个函数(无参数),没有return返回值时
func s3() {fmt.Println("szq")
}// 定义一个函数(无参数),有return返回值时(需要给返回值定义一个类型)
func s4() string {return "sudada"
}// return返回值 可以命名(命名后可以直接使用,因为已经做了声明),也可以不命名
// return返回值"szq"在已经声明好的情况下,return后可以什么都不写,默认返回的就是"szq"
func s5(x int, y int) (szq int) {szq = x + yreturn // 这里就可以不写szq,写上也没关系
}// 多个返回值
func s6() (int, string) {return 1, "2"
}// 参数类型的简写(2个参数连续且类型一致时,可以这么写)
func s7(x, y int) int {return x + y
}// 可变长参数(...)必须放在函数参数的最后, y可以不传参,可以传一个参数,也可以传多个参数(拿到的就是一个切片类型的值)
func s8(x string, y ...int) {fmt.Println(x)fmt.Println(y) // [1 2 3 4] 拿到的是一个int类型的切片
}// go语音中函数没有默认参数的概念
func main() {fmt.Println(s1(1, 2))s2(2, 3)s3()fmt.Println(s4())fmt.Println(s5(2, 2))fmt.Println(s6())s8("szq")
}

1.3、函数传参

1.3.1、类型简写

函数的参数中如果相邻变量的类型相同,则可以省略类型,例如:

// 参数类型的简写(2个参数连续且类型一致时,可以这么写)
func s7(x, y int) int {return x + y
}

上面的代码中,s7函数有两个参数,这两个参数的类型均为int,因此可以省略x的类型,因为y后面有类型说明,x参数也是该类型。

1.3.2、可变长参数

可变参数是指函数的参数数量不固定。Go语言中的可变参数通过在参数名后加...来标识
注意:可变参数通常要作为函数的最后一个参数。

// 可变长参数(...)必须放在函数参数的最后, y可以不传参,可以传一个参数,也可以传多个参数(拿到的就是一个切片类型的值)
func s8(x string, y ...int) {fmt.Println(x)fmt.Println(y) // [1 2 3 4] 拿到的是一个int类型的切片
}

可变长参数使用:

func intSum2(x ...int) int {fmt.Println(x) // x是一个切片sum := 0for _, v := range x {sum = sum + v}return sum
}func main() {ret1 := intSum2()ret2 := intSum2(10)ret3 := intSum2(10, 20)ret4 := intSum2(10, 20, 30)fmt.Println(ret1, ret2, ret3, ret4) //0 10 30 60
}

固定参数搭配可变参数使用时,可变参数要放在固定参数的后面,示例代码如下:

func intSum3(x int, y ...int) int {fmt.Println(x, y)sum := xfor _, v := range y {sum = sum + v}return sum
}func main() {ret5 := intSum3(100)ret6 := intSum3(100, 10)ret7 := intSum3(100, 10, 20)ret8 := intSum3(100, 10, 20, 30)fmt.Println(ret5, ret6, ret7, ret8) //100 110 130 160
}

本质上,函数的可变参数是通过切片来实现的。

1.4、函数 返回值

Go语言中通过return关键字向外输出返回值。

1.4.1、多返回值
Go语言中函数支持多返回值,函数如果有多个返回值时必须用()将所有返回值包裹起来。

func calc(x, y int) (int, int) {sum := x + ysub := x - yreturn sum, sub
}
func main() {a, b := calc(1, 2)fmt.Println(a)fmt.Println(b)
}

1.4.1、多返回值命名
函数定义时可以给返回值命名,并在函数体中直接使用这些变量,最后通过return关键字返回。

// return返回值 可以命名(命名后可以直接使用,因为已经做了声明),也可以不命名
// return返回值"szq"在已经声明好的情况下,return后可以什么都不写,默认返回的就是"szq"
func s5(x int, y int) (szq int) {szq = x + yreturn // 这里就可以不写szq,写上也没关系
}// 例子2
func calc(x, y int) (sum, sub int) {sum = x + ysub = x - yreturn
}func main() {a, b := calc(1, 2)fmt.Println(a)fmt.Println(b)
}

二、函数作用域

2.1、全局变量

全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效。 在函数中可以访问到全局变量。

函数中查找变量的顺序:
   1.先在函数的内部查找
   2.找不到就往函数的外面查找,一直找到全局,如果找不到就报错。

var szq = 123func s0()  {fmt.Println(szq)
}func main() {s0() // 123
}

2.2、局部变量

1.局部变量又分为两种: 函数内定义的变量无法在该函数外使用

func testLocalVar() {//定义一个函数局部变量x,仅在该函数内生效var x int64 = 100fmt.Printf("x=%d\n", x)
}func main() {testLocalVar()fmt.Println(x) // 此时无法使用变量x
}

2.如果局部变量和全局变量重名,优先访问局部变量

//定义全局变量num
var num int64 = 10func testNum() {num := 100fmt.Printf("num=%d\n", num) // 函数中优先使用局部变量
}
func main() {testNum() // num=100
}

2.3、语句块定义的变量

1.通常我们会在if条件判断、for循环、switch语句上使用这种定义变量的方式。

func testLocalVar2(x, y int) {fmt.Println(x, y) //函数的参数也是只在本函数中生效if x > 0 {z := 100  //变量z只在if语句块生效fmt.Println(z)}fmt.Println(z) //此处无法使用变量z
}
func main() {testLocalVar2(1,2)
}

2.还有for循环语句中定义的变量,也是只在for语句块中生效:

func testLocalVar3() {for i := 0; i < 10; i++ {fmt.Println(i) //变量i只在当前for语句块中生效}fmt.Println(i) //此处无法使用变量i
}func main() {testLocalVar3()
}

三、函数类型与变量

3.1、定义函数类型

1.什么是函数类型,举个例子:

// 函数作为参数赋值给变量时,有哪些类型
func s1(){fmt.Println("szq")
}func s2() int{return 18
}func s3(x int) int{return x+1
}func main() {a := s1// 打印变量a的类型fmt.Printf("%T\n",a) //func():这是一个普通的函数类型b := s2// 打印变量b的类型fmt.Printf("%T\n",b) //func() int :这是一个函数类型(包括函数的返回值类型)c := s3// 打印变量c的类型fmt.Printf("%T\n",c) //func(int) int :这是一个函数类型(包括函数的参数类型和函数的返回值类型)
}

2.函数作为一个参数

// 定义函数s1
func s1() int {return 18
}// s1函数作为参数传递给s2函数
func s2(x func() int){res := x()fmt.Println(res)
}func main() {re1 := s1 // 将函数赋值给变量re1fmt.Printf("%T\n",re1) // func() ints2(s1)  // 函数s1作为参数传递给函数s2(s1函数的类型必须满足s2的接收参数类型,即:func() int)s2(re1) // 变量re1作为参数传递给函数s2(变量re1的类型必须满足s2的接收参数类型,即:func() int)
}

3.函数作为一个返回值

// 定义函数s1
func s1() int {return 18
}func ff(a int,b int)int{return a+b
}// 函数作为一个返回值返回
// x func() int        表示x的类型为:func() int
// y func(int,int)int  表示s3函数的返回值类型为:func(int,int)int
func s3(x func() int)(y func(int,int)int){fmt.Println(x())res := func(a int,b int)int{return a+b}//res := ff // 这里也可以换一种写法,ff函数的格式需要满足y即可return res
}func main() {szq:=s3(s1) // 把函数s1做为参数传入到函数s3中,执行函数s3的代码后拿到一个返回值resfmt.Println(szq(1,2)) // 拿到的返回值res类型为"函数类型:func(int,int)int",那么就可以正常的传值,查看执行结果
}
//返回结果:
//18
//3

3.2、函数类型变量 (变量的类型为函数类型,然后为该变量赋值)

了解以上函数类型之后,我们可以使用type关键字来定义一个函数类型,具体格式如下:
type calculation func(int, int) int
上面语句定义了一个calculation类型,它是一种函数类型这种函数接收两个int类型的参数并且返回一个int类型的返回值。

// 定义一个函数类型
type calculation func(int, int) int// 定义一个全局变量c,c的类型为calculation
var c calculation// 定义一个普通函数,类型为:add(x, y int) int
func add(x, y int) int {return x + y
}func main() {c = add  // 给变量c做赋值操作(变量c = add函数)fmt.Println(add(1,2))  // 3fmt.Printf("%T\n",c)   // main.calculationfmt.Println(c(5,5))    // 像调用add一样调用c,返回值为:10f := add  // 将函数add赋值给变量ffmt.Printf("type of f:%T\n", f) // type of f:func(int, int) intfmt.Println(f(10, 20))          // 像调用add一样调用f,返回值为:30
}

四、defer语句 

4.1、Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

举个例子:

func main() {fmt.Println("start")defer fmt.Println(1)defer fmt.Println(2)defer fmt.Println(3)fmt.Println("end")
}
//输出结果:
//start
//end
//3
//2
//1

由于defer语句延迟调用的特性,所以defer语句能非常方便的处理资源释放问题。比如:资源清理、文件关闭、解锁及记录时间等。

4.2、defer执行时机

在Go语言的函数中return语句在底层并不是原子操作,它分为给返回值赋值RET(return)指令两步。defer语句执行的时机就在返回值赋值操作后,RET(return)指令执行前。具体如下图所示:

defer执行时机

4.3、defer经典案例

// 第一步:返回值赋值
//defer
//第二步:真的的return,返回一个值func f1() int {x := 5defer func() {x++  // 修改的是x,不是返回值}()return x
}func f2() (x int) {defer func() {x++}()return 5   // 返回值为x
}func f3() (y int) {x := 5defer func() {x++  // 修改的是x}()return x // 返回值为y,y的值=x=5
}
func f4() (x int) {defer func(x int) {x++  // 改变的是函数中的副本}(x)return 5 // 返回值=x=5
}func main() {fmt.Println(f1()) //5fmt.Println(f2()) //6fmt.Println(f3()) //5fmt.Println(f4()) //5
}

4.4、defer面试题

func calc(index string, a, b int) int {ret := a + bfmt.Println(index, a, b, ret)return ret
}func main() {// var x int = 1x := 1// var y int = 2y := 2// 函数内套用函数调用时,代码走到这一层就会先执行函数内的函数,会把对应变量的值传过去。 即:defer calc("AA", 1, calc("A", 1, 2)) == defer calc("AA", 1, 3),详见下面的分析结果:defer calc("AA", x, calc("A", x, y))// 这里的x因为在前面已经做了定义,所以可以直接用"="号赋值x = 10// 函数内套用函数调用时,代码走到这一层就会先执行函数内的函数,会把对应变量的值传过去即:defer calc("BB", 10, calc("B", 10, 2)) == defer calc("BB", 10, 12),详见下面的分析结果:defer calc("BB", x, calc("B", x, y))// 这里的y因为在前面已经做了定义,所以可以直接用"="号赋值y = 20
}// 分析以上代码的执行过程:
// 1)x := 1
// 2)y := 2
// 3)defer calc("AA", x, calc("A", x, y)) == defer calc("AA", 1, calc("A", 1, 2)) == defer calc("AA", 1, 3)
// 4)x = 10
// 5)defer calc("BB", x, calc("B", x, y)) == defer calc("BB", 10, calc("B", 10, 2)) == defer calc("BB", 10, 12)
// 6)y = 20
// 7)defer calc("BB", 10, 12) == BB 10 12 22
// 8)defer calc("AA", 1, 3) == AA 1 3 4//输出结果:
//A 1 2 3      先执行函数内的函数
//B 10 2 12    先执行函数内的函数
//BB 10 12 22  在按照defer的逻辑,最后定义的最先执行
//AA 1 3 4     按照defer的逻辑,最先定义的最后执行

五、匿名函数和闭包

5.1、匿名函数 (匿名函数多用于实现回调函数和闭包,匿名函数一般都用在函数内部)

函数当然还可以作为返回值,但是在Go语言中函数内部不能再像之前那样定义函数了,只能定义匿名函数。匿名函数就是没有函数名的函数,匿名函数的定义格式如下:
func(参数)(返回值){
    函数体
}

1.匿名函数作为变量执行,例子如下:

// 匿名函数使用1
var f1 = func(x,y int){fmt.Println(x+y)
}func main() {f1(1,2) // 调用匿名函数,返回值为:3// 匿名函数使用2f2 := func(x,y int){fmt.Println(x+y)}f2(10,20) // 调用匿名函数,返回值为:3// 如果只是调用一次的函数,可以简写成"立即执行函数"func(x,y int){fmt.Println(x+y)}(2,3) // 调用"立即执行函数",返回值为:5
}

2.匿名函数作为立即执行函数(只是一次调用的函数),例子如下:

func main() {// 如果只是调用一次的函数,可以简写成"立即执行函数"func(x,y int){fmt.Println(x+y)}(2,3) // 调用"立即执行函数",返回值为:5
}

5.2、闭包 (一个函数除了引用函数内定义的变量外,还引用了函数外部的变量)

闭包的底层原理:
  1.函数可以作为返回值,
  2.函数内部查找顺序,现在函数内部找,找不在再往外部找。

闭包指的是一个函数和与其相关的引用环境组合而成的实体。简单来说,闭包=函数+引用环境。 首先我们来看一个例子:

// 闭包的实际应用,要求:s1(s2) 把s2作为参数传入到s1
func s1(f func()) {fmt.Println("s1")f()
}func s2(x, y int) {fmt.Println("s2")fmt.Println(x + y)
}//s3函数要接收s2函数的传参,并且返回值的类型要符合s1函数参数类型
//f func(int, int), x, y int 这些都是给s2函数使用的
//func() 这个是给s1函数使用的
func s3(f func(int, int), x, y int) func() {res := func() {f(x, y)}return res // 这里的返回值res是一个func()类型,符合s1函数的接收类型
}func main() {ret := s3(s2, 100, 300) // 这里ret也就等于s3函数内的ress1(ret)                 // s1函数传入ret,本质上执行的是s2函数的代码。
}//输出结果
//s1
//s2
//400

例子2:在函数内修改函数的参数值

func calc(base int) (func(int) int, func(int) int) {add := func(i int) int {base += ireturn base}sub := func(i int) int {base -= ireturn base}return add, sub
}func main() {f1, f2 := calc(10)fmt.Println(f1(1), f2(2)) //11 9,这里每次改的都是calc函数内的base,也就是说随着每次的改修,base的值会发生改变。fmt.Println(f1(3), f2(4)) //12 8fmt.Println(f1(5), f2(6)) //13 7
}

六、内置函数

6.1、内置函数介绍

内置函数介绍
close主要用来关闭channel
len用来求长度,比如string、array、slice、map、channel
new用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针
make用来分配内存,主要用来分配引用类型,比如chan、map、slice
append用来追加元素到数组、slice中
panic和recover用来做错误处理

6.2、panic 错误处理

func funcA() {fmt.Println("func A")
}func funcB() {panic("出现了严重的错误!")  // 主动报错
}func funcC() {fmt.Println("func C")
}
func main() {funcA()funcB()funcC()
}// 输出结果:
//	func A   			  // 报错之前执行的代码
//	panic: 出现了严重的错误! // 报错的输出//	goroutine 1 [running]:
//	main.funcB(...)     // 报错的代码位置点
//		/Users/suzhaoqiang/Desktop/Go/Goland_Document/学习过程/2021-8-16/05.go:10
//	main.main()         // 报错代码的执行点
//		/Users/suzhaoqiang/Desktop/Go/Goland_Document/学习过程/2021-8-16/05.go:18 +0x96

6.3、panic + recover 接收错误信息,代码继续执行

注意:
recover()必须搭配defer使用。
defer一定要在可能引发panic的语句之前定义。

func funcA() {fmt.Println("func A")
}func funcB() {defer func() {err := recover() // recover()拿到的就是panic的输出。使用recover()后程序不会崩溃退出,继续往下执行。fmt.Println(err)}()panic("出现了严重的错误!") // defer要在panic之前定义,否则panic程序崩溃,没法执行defer语句了。
}func funcC() {fmt.Println("func C")
}
func main() {funcA()funcB()funcC()
}//输出结果:
//func A
//出现了严重的错误!
//func C

 

http://www.lbrq.cn/news/1592587.html

相关文章:

  • 建网站需要什么技术/网上营销策略有哪些
  • 网站怎么做会员系统/社群营销成功案例
  • 山东建设管理局网站/网站统计工具有哪些
  • 长沙移动网站建设哪家好/网站推广排名优化
  • 用源码网站好优化吗/微信怎么推广找客源
  • 创建好网站如何把浏览器/建站推广
  • 昆山做网站需要多少钱/百度账号快速注册入口
  • 衡水网站制作/网络优化seo
  • 网站开发是什么专业/长沙百度关键词排名
  • 重庆工程建设招标网官方网站/长沙营销型网站建设
  • 企业建立网站的目的/企业培训课程名称
  • wordpress 支付宝插件下载/博客seo教程
  • html5高端酒水饮料企业网站模版/线上拓客渠道有哪些
  • 重庆的汽车网站建设/企业官网搭建
  • 网站开发后期要解决的问题/pc网站建设和推广
  • 传统网站开发/长沙百度网站排名优化
  • 区政府网站建设规范报告/广州网页搜索排名提升
  • 一些房产网站是怎么做的/网站关键词怎么添加
  • wordpress升级原理/网络优化排名培训
  • 莆田网站制作方案定制/建网站平台
  • 网站建设分金手指专业七/网络推广费用
  • 东莞 外贸网站 建站/快速整站优化
  • 网站做查赚钱/福州百度seo代理
  • 宣传片拍摄制作公司/长尾词优化外包
  • wordpress 2.9.1漏洞/搜索引擎优化方法与技巧
  • 河南华盛建设集团网站/seo搜索引擎实训心得体会
  • 国际物流网站制作模板/如何做市场营销推广
  • 韩韩良品只做性价比网站下载/seo排名赚app靠谱吗
  • 独立网站上后台怎么管理图片/廊坊百度关键词优化怎么做
  • 做平面什么网站好用/爱站网关键词搜索
  • 七、Linux Shell 与脚本基础
  • LinkedList 深度解析:核心原理与实践
  • 游戏画面总是卡顿怎么办 告别延迟畅玩游戏
  • 机器学习 集成学习之随机森林
  • 行为模式-模板方法模式
  • 【C++】Stack and Queue and Functor