【Go语言快速上手(二)】 分支与循环&函数讲解

简介: 【Go语言快速上手(二)】 分支与循环&函数讲解

1. 前言

经过第一篇文章的学习,现在我们对GO已经有了一个初步的了解,接下来会站在使用它的角度,给大家讲解一些语法和GO语言的组件

本章重点:

本篇文章着重讲解GO语言的分支与循环语句,以及GO语言中的函数的特性,以及函数是怎样定义的?最后会讲解几个特殊的函数,包括init函数,匿名函数,以及defer关键字的用途,字符串函数和日期函数


2. 分支与循环

GO语言中的分支循环和C很类似,也是用if,else if,else以及for循环,switch语句来完成任务.比较特别的是,GO语言中没有while循环,但是新增了一个叫for range的东西,后面会一一讲解

if,else语句

var age int = 18
if age>=18{
  fmt.Println("可以去网吧")
}else{
  fmt.Println("不能去网吧")
}

GO语言比较特别的是,if语句的判断条件不用加括号,判断条件可直接写.除此之外,GO语言的if,else语句可不是能随意写的,下面这种写法就是错误的

var age int = 18
if age>=18{
  fmt.Println("可以去网吧")
}
else{
  fmt.Println("不能去网吧")
}

2.1 for循环和for range

代码实例:

var str string = "abcdefg"
for i := 0;i<len(str);i++{
  fmt.Println(str[i])
}

go语言的for循环中的初始表达式位置,不能使用var来定义变量,只能用:=的形式,并且,for循环的括号也是可以省略的,甚至连初始表达式和迭代因子都可以省略.注:len是内置函数,可以求字符串/数组的长度

for range

for range是GO语言独有的一种迭代结构,它可以遍历字符串,数组,切片,map等诸多类型,它的语法有一点像C++11中的范围for,它的一般形式为: for key,value := range coll{}

代码实例

var str string = "abcdefg"
for key,value := range str{
  fmt,Printf("下标为: %d,值为: %c",key,value)

for range中的key代表数组/字符串的下标,也可以叫索引,而value代表数组/字符串中的元素. 如果你不想接收下标,可以这样写: for _,value := range str{}.


2.2 switch语句

代码实例

var grade int = 81
switch grade/10{
  case 10:
  fmt.Println("优秀")
  case 9:
  fmt.Println("优秀")
  case 8:
  fmt.Println("良好")
  case 7:
  fmt.Println("良好")
  case 6:
  fmt.Println("及格")
  default:
  fmt.Println("不及格")
}

GO语言中的switch语句中的每一个case都自带break,这和C语言有大不同,GO语言的switch语句还有以下特征,大家可以下来自行验证


3. 函数的引入

代码实例:

func add(x int,y int) int{
  return x+y
}
func main(){
  var age int = add(10,20)
  fmt.Println(age)
}

GO语言中函数的传参默认也是传递,和C一样,并且GO语言不支持函数重载,除此之外,GO语言的函数命名也有讲究,细节如下:

在GO语言中,函数也是一种数据类型,它可以赋值给一个变量,也可以当作其他函数的形参被传入函数中,这一点类似于C++11当中的function,并且,GO语言的函数还可以重命名返回值,注:GO语言的函数可能有多个返回值,有多个返回值时需要把返回值带上括号

代码实例一:

func sub(x int,y int) int{
  return x-y
}
func main(){
  function := sub
  var tmp int = function(20,10)
  fmt.Println(tmp)
}

代码实例二:

//写法一
func mytask(x int,y int) (int,int){
  return x+y,x-y
}
//写法二
func mytask(x int,y int) (sum int,sub int){//重命名返回值
  sum := x+y
  sub := x-y
  return //不用写特定的变量或值,系统会自动返回sum和sub两个变量
}

4. 包的引入

前面一直有在说包,那到底什么是包?包实际上就是一个文件夹,这个文件夹中存放了你的.go文件,那么为什么要有包?在C++中我们常说到,实现一个项目时,不可能只在一个源文件中进行,我们可能会定义多个源文件,而在GO语言中我们常常称使用多个包完成不同的任务,并且引入包可以解决同名函数等问题

注意事项: GO语言的第一行代码往往是package main,这是在main函数中需要写出package main,但是假如当前文件没有main函数,它只是一组方法的集合,那么这个时候就不能写成package main了,假设这个.go文件所在的文件夹叫tmp,那么就应该写成: package tmp,以此类推

只要在同一个文件下,所有的.go文件都属于一个包,所以在同一个文件下,不同的源文件也不能定义同名函数,因为一个包只能有唯一命名的函数


5. init函数讲解

init函数,又称初始化函数,可以用来进行一些初始化工作,每一个源文件中都可以包含一个init函数,该函数会在main函数执行前就被GO运行框架调用

两个问题:

  1. 全局变量,init函数,main函数的执行顺序
  2. 多个源文件都有init函数时的执行顺序
var age int = var(10,20)
func var(x int,y int) int{
  fmt,Println("全局变量被执行")
  return x+y
}
func init(){
  fmt,Println("init函数被执行")
}
func main(){
  fmt,Println("main函数被执行")
}

结论:

  • 全局变量>init>main函数
  • 其他包的init函数>main包的init函数

6. 匿名函数讲解

代码实例:

func main(){
  var ret int = func(x int,y int) int{
    return x+y
  }(10,20)//最后进行传参
  fmt.Println(ret)
}

7. defer关键字讲解

在函数中,程序员经常需要创建资源(比如堆区资源,文件描述符等),为了在函数执行完毕后,能够很好的释放这些资源,GO语言提供了defer关键字

func add(x int,y int) int{
  defer fmt.Printf("x的值为: %d",x)
  defer fmt.Printf("y的值为: %d",y)
  x += 100
  y +=50
  var sum int = x+y
  fmt.Println(sum)
  return sum
}
func main(){
  var tmp int = add(10,20)
  fmt.Println(tmp)
}

GO中,语句defer关键字修饰的语句时,不会立刻执行此语句,而是将此语句压入到一个栈中,等整个函数调用结束时再执行栈中的语句,并且,压入栈中的语句的值已经定了,即使在后面修改了值(比如上面代码中的x和y),栈中也不会受影响

使用场景: 打开文件描述符时,立马用defer写一个关闭文件描述符的语句,就不会遗忘释放资源


8. 字符串函数讲解

字符串函数有很多,大家不必全部背下来,有个影响就行,到时候真正要用的时候再查文档即可

有些字符串函数有两个返回值,第二个往往是err,代表执行这个函数时是否出错,如果你不想接收它,直接用下划线_省略掉即可.注意,字符串函数需要import包:strconv,而strings是内置的包,可以直接使用

var str string = "abcdefg"
r := []rune(str)//将str转换为切片后再使用
for i:=0;i<len(r);i++{
  fmt.Println(r[i])
}
pos := strings.lndex("i love cpp,i love golang",'c')

字符串函数很多,就不一一举例子了,大家可以下来试着编写一下demo


9. 内置函数

golang设计者为了编程方便,提供了一些不用导包就可以直接使用的函数,称为内置函数,下面是常见的内置函数:

  • len函数: 统计字符串/数组/切片等的长度
  • new函数: 分配内存,主要用来分配值类型,如:int,float,string,数组,结构体
  • make函数: 分配内存,主要用于分配引用类型,如:指针,切片,map等
  • new和make函数都是在堆区开辟空间

10. 总结以及拓展

GO语言还是挺好上手了,基本上写一遍就能知道它的用法,如果你基础语言学的比较扎实,你甚至可以想象出它底层是如何设计的,本系列文章的重点将放在GO语言的快速上手,所以就没有讲底层的原理,如果是校招要想找GO语言相关工作的同学,我还是建议你们多多深造一下

拓展:GO语言的API接口

Go语言标准文档(中文版)


🔎 下期预告:错误处理,数组以及切片 🔍


相关文章
|
19天前
|
存储 Java Go
对比Java学习Go——函数、集合和OOP
Go语言的函数支持声明与调用,具备多返回值、命名返回值等特性,结合`func`关键字与类型后置语法,使函数定义简洁直观。函数可作为一等公民传递、赋值或作为参数,支持匿名函数与闭包。Go通过组合与接口实现面向对象编程,结构体定义数据,方法定义行为,接口实现多态,体现了Go语言的简洁与高效设计。
|
2月前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。
|
2月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
3月前
|
JSON 前端开发 Go
Go语言实战:创建一个简单的 HTTP 服务器
本篇是《Go语言101实战》系列之一,讲解如何使用Go构建基础HTTP服务器。涵盖Go语言并发优势、HTTP服务搭建、路由处理、日志记录及测试方法,助你掌握高性能Web服务开发核心技能。
|
3月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
270 0
|
4月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
4月前
|
人工智能 Dart Go
Go语言中的make和new函数的区别及使用场景
本文详细解析了Go语言中`make`和`new`函数的使用方法及区别。`make`用于创建切片、映射和通道等引用类型,返回初始化后的值;`new`用于创建任意类型的零值对象,返回指向该对象的指针。文章通过多个示例说明两者的应用场景,并总结了面试中可能遇到的相关问题,如底层实现、使用场景及优缺点等,帮助读者更好地理解和区分这两个函数。
123 1
|
5月前
|
分布式计算 Go C++
初探Go语言RPC编程手法
总的来说,Go语言的RPC编程是一种强大的工具,让分布式计算变得简单如同本地计算。如果你还没有试过,不妨挑战一下这个新的编程领域,你可能会发现新的世界。
128 10
|
8月前
|
存储 缓存 安全
Go 语言中的 Sync.Map 详解:并发安全的 Map 实现
`sync.Map` 是 Go 语言中用于并发安全操作的 Map 实现,适用于读多写少的场景。它通过两个底层 Map(`read` 和 `dirty`)实现读写分离,提供高效的读性能。主要方法包括 `Store`、`Load`、`Delete` 等。在大量写入时性能可能下降,需谨慎选择使用场景。
|
11月前
|
存储 负载均衡 监控
如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
在数字化时代,构建高可靠性服务架构至关重要。本文探讨了如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
227 1