go:函数高级、包的使用、if-else、循环、switch、数组
一、函数高级
1、函数的参数和返回值都是类型的一部分,函数可以赋值给一个变量,有两种情况:
test3 函数,接收一个参,参数是函数类型:没有参数没有返回值
test3 有返回值,返回值是个函数:函数有两个参数,一个返回值
有参数有返回值的带代码如下:
package main
import "fmt"
func main() {
f := test3(func() {
fmt.Println("被传入的函数")
})
res := f(10, 19)
fmt.Println(res)
}
func test3(a func()) func(int, int) int {
a()
return func(x, y int) int {
return x + y
}
}
2、类型重命名
可以给类型重命名
如果 type Myint int 相当于我们新定义了一个类型,叫Myint
如果 type Myint = int 只是重命名,没有新定义类型
type MyFunc func(int, int) int
type Myint = int
func test3(a func()) MyFunc {
a()
return func(x, y int) int {
return x + y
}
}
3、函数可变长参数
可以传任意长度的int类型参数
func test4(a ...int) {
fmt.Println(a) //[3 4 5 6 7 7 8 89 9 99] 切片
fmt.Printf("%T", a) // 类型是 int类型切片 []int
}
4、defer 关键字
package main
import "fmt"
func main() {
//var a Myint = 9
//var b int = 19
//fmt.Println(a + b)
//fmt.Println(6,3,4,5,5,6,76,7,8)
// 完整定义
//var f MyFunc = test3(func() {
// fmt.Println("被传入的函数")
//})
//res := f(10, 19)
//fmt.Println(res)
// 3 可变长参数
//test4(3, 4, 5, 6, 7, 7, 8, 89, 9, 99)
// 4 defer 延迟调用, 当前函数所有代码都执行完了,再执行defer的内容,先注册,后调用 ,先写的defer后来执行
//var a = 10
//defer func(i int) {
// fmt.Println(i)
// fmt.Println("我很帅")
//
//}(a)
defer fmt.Println("我很帅")
defer fmt.Println("我很帅222")
//a = 99
fmt.Println("我不觉得")
fmt.Println("我也不觉得")
}
二、包的使用
python 模块和包
模块是一个py文件
包是一个文件夹 有 init
go的包
go中的包是在一个文件夹下,这个文件夹下所有go文件的第一行要声明包(一堆go文件的组合)
当我们在一个文件夹内编写多个go文件的时候,包名必须一致
总结
- 包内部,大写开头,表示导出 变量,函数。。。
- 包内部的变量函数,只能定义一次
- 包内部的所有东西,在包内部直接使用
- 包名可以跟文件夹名不一样,但是一个文件夹下只能有一个包
- 导入包,按路径导入,如果不重命名,就是文件夹必须跟包名一样
- 如果文件夹跟包名不一样,要重命名,可以命名成任意的,但是我们叫了包名 import lqz "go_day03/utils"
- 可以命名成任意的包名 import qqq "go_day03/utils"
- 以后使用包名. 调用即可
- 包内的init函数,可以定义多次,只要导入包,就会依次执行init
- 导入包,必须使用,不使用就报错,现在就不用,只想执行init, import _ "go_day03/utils"
- 一个文件夹下可以再建文件夹建新的包,各个文件夹直接没有必然联系,只是文件夹层级关系(导入使用即可)
- 使用的go mod模式,从1.11后都是这种模式,项目根路径下会有一个go.mod
go path模式介绍
之前有个go path模式,已经弃用了,它的包导入,不是从项目路径下开始导入,而是从go path 的src路径下路径下开始导入
go 安装第三方包(以gin包为例)
go语言中的包目前没有同意的存储仓库,因此大部分的go包都是从github中下载的,也可以使用第三方代理下载
ps:github下载速度感人!
主流的代理
- 阿里云 https://mirrors.aliyun.com/goproxy/(推荐使用)
- nexus社区 https://gonexus.dev
- goproxy.io的 https://goproxy.io/ (推荐使用)
- athens的公共服务 https://athens.azurefd.net
- 官方提供 https://gocenter.io https://proxy.golang.org
- 七牛云 https://goproxy.cn
配置代理
1、配置局部代理(goland中启用代理)
打开设置界面后,先去找下图的界面是否跟你的界面一样(新版本会不一样),如果一样按照他的操作设置
如果你发现自己的界面跟上图的界面不一样,就参考这张图中的配置代理设置(需要手动输入)
还有一种设置方式
2、配置全局代理
打开cmd界面或是goland中的terminal界面,输入下方命令
1.打开模块支持
go env -w GO111MODULE=on
2.取消代理
go env -w GOPROXY=direct
3.取消校验
go env -w GOSUMDB=off
设置不走 proxy 的私有仓库或组,多个用逗号相隔(可选)
go env -w GOPRIVATE=git.mycompany.com,github.com/my/private
备注:-w 标记 要求一个或多个形式为 NAME=VALUE 的参数且覆盖默认的设置
gin包简介
gin包是一个框架,相当于python中的flask
安装gin包:
go get -u github.com/gin-gonic/gin
操作代码
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"code": "100",
"message": "成功",
})
})
r.GET("/index", func(c *gin.Context) {
c.HTML(200, "index.html", gin.H{"name": "刘清政", "age": 19})
})
r.Run() // listen and serve on 0.0.0.0:8080
}
这里我们不做具体讲解,但是我们可以看到他这里路由的注册也是类似django的,路由跟视图函数的内存地址绑定
三、if-else
#基本格式
if 条件{
}else if 条件{
}else{
}
ps:如果else和括号,不在同一行,会报错,他们算是一个整体,不能分割(比python中严格)
package main
import (
"fmt"
)
// if-else
func main() {
score := 55
if score >= 90 {
fmt.Println("优秀")
} else if score >= 80 && score < 90 {
fmt.Println("良好")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
}
四、循环
# python while for
# go 只有 for循环
# java while ,for do while
# go的for循环能实现while循环的功能
package main
// 循环
func main() {
// 1 基本语法 for关键字 定义变量i=0;i<10;i++{} 三部分都可以省略,但是一般会保留第二部分,第二部分是条件
//// 2 循环打印0--9
//for i := 0; i < 10; i++ {
// fmt.Println(i)
//}
//fmt.Println(i) // i的作用域范围只在for内部有效
// 3 循环打印0--9 省略掉第一部分 分号不能省
//i := 0
//for ; i < 10; i++ {
// fmt.Println(i)
//}
//fmt.Println(i) // 10
// 4 循环打印0--9 第三部分 分号不能省
//for i := 0; i < 10; {
// fmt.Println(i)
// i++
//}
// 5 循环打印0--9 省略第一部分和第三部分 分号能省略
//i := 0
//for i < 10 {
// fmt.Println(i)
// i++
//}
// 6 for 条件 {} while 循环
//for true {
// fmt.Println("llll")
//}
// 死循环
//for {
// fmt.Println("llll")
//}
//7 上面是基于索引的循环,这个案例是基于迭代的
s := "lqz国中"
//for i, v := range s {
// fmt.Println(i)
// fmt.Println(string(v))
//}
//for i := 0; i < len(s); i++ {
// fmt.Println(string(s[i]))
//}
}
五、switch
switch 是一个条件语句,用于将表达式的值与可能匹配的选项列表进行比较,并根据匹配情况执行相应的代码块,优雅的替换掉else-if
package main
import "fmt"
func main() {
// 1 switch 基本使用
//score := 90
//switch score {
//case 90:
// fmt.Println("我是90")
//case 80:
// fmt.Println("我是80")
//case 70:
// fmt.Println("我是70")
//}
//// 2 default 的使用
//score := 99
//switch score {
//case 90:
// fmt.Println("我是90")
//case 80:
// fmt.Println("我是80")
//case 70:
// fmt.Println("我是70")
//default:
// fmt.Println("不知道")
//}
// 3 多表达式判断
//score := 66
//switch score {
//case 90, 91, 92, 98, 99:
// fmt.Println("我是90")
//case 80, 88:
// fmt.Println("我是80")
//case 70:
// fmt.Println("我是70")
//default:
// fmt.Println("不知道")
//}
// 4 无表达式
//score := 66
//switch {
//case score > 90:
// fmt.Println("我是90")
//case score > 80 && score < 90:
// fmt.Println("我是80")
//case score >= 60:
// fmt.Println("大于60")
//default:
// fmt.Println("不知道")
//}
//5 Fallthrough 默认情况下,每个条件之间完,默认加break,但是也不用加,其他语言要加,其他语言去掉break,会无条件执行下一个case
// 要无条件执行下一个case,需要使用fallthrough
score := 99
switch {
case score > 90:
fmt.Println("我是90")
case score > 80 && score < 90:
fmt.Println("我是80")
fallthrough // 无条件执行下一个case
case score >= 60 && score <= 80:
fmt.Println("大于60")
fallthrough
default:
fmt.Println("不知道")
}
}
六、数组
# 数组是同一类型元素的集合。例如,整数集合 5,8,9,79,76 形成一个数组。
# Go 语言中不允许混合不同类型的元素,例如包含字符串和整数的数组
# 数组是连续存储,存储同一个类型的数据结构
七、作业
python实现链表
链表的概念
1、链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,有一系列结点(地址)组成,结点可动态的生成。
我们可以把单链表类比成火车,每一列火车由若干个车厢组成,每个车厢就是一个Node结点,由多个Node结点组成的对象就是链表对象。火车的不同车厢之间都是通过挂钩连接的,当两个车厢之间脱钩之后,两个车厢就没有任何关系了。
Python 中没有内置的链表数据结构,但可以通过定义类来实现链表。
链表是一种数据结构,由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。相比于数组,链表的优势在于可以高效地进行插入和删除操作,但是访问元素需要从头开始遍历链表,因此访问元素的时间复杂度为 O(n)。
以下是一个简单的 Python 链表实现:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def add_node(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
else:
current = self.head
while current.next is not None:
current = current.next
current.next = new_node
def print_list(self):
current = self.head
while current is not None:
print(current.data, end=" ")
current = current.next
print()
上面的代码定义了一个 Node
类和一个 LinkedList
类。Node
类表示链表中的节点,包含一个数据元素和一个指向下一个节点的指针。LinkedList
类表示链表本身,包含一个指向链表头节点的指针。
LinkedList
类定义了两个方法:add_node()
用于向链表中添加节点,print_list()
用于打印链表中的所有元素。
以下是一个使用链表的例子:
my_list = LinkedList()
my_list.add_node(3)
my_list.add_node(1)
my_list.add_node(4)
my_list.add_node(1)
my_list.add_node(5)
my_list.add_node(9)
my_list.print_list() # 输出:3 1 4 1 5 9
请注意,这只是一个简单的链表实现,还有很多方面可以进行改进和优化。