Go-day3——函数高级、包的使用、if-else、循环、switch、数组

发布时间 2023-04-26 17:27:29作者: 致丶幻


一、函数高级

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文件的时候,包名必须一致

总结

  1. 包内部,大写开头,表示导出 变量,函数。。。
  2. 包内部的变量函数,只能定义一次
  3. 包内部的所有东西,在包内部直接使用
  4. 包名可以跟文件夹名不一样,但是一个文件夹下只能有一个包
  5. 导入包,按路径导入,如果不重命名,就是文件夹必须跟包名一样
    1. 如果文件夹跟包名不一样,要重命名,可以命名成任意的,但是我们叫了包名 import lqz "go_day03/utils"
    2. 可以命名成任意的包名 import qqq "go_day03/utils"
    3. 以后使用包名. 调用即可
  6. 包内的init函数,可以定义多次,只要导入包,就会依次执行init
  7. 导入包,必须使用,不使用就报错,现在就不用,只想执行init, import _ "go_day03/utils"
  8. 一个文件夹下可以再建文件夹建新的包,各个文件夹直接没有必然联系,只是文件夹层级关系(导入使用即可)
  9. 使用的go mod模式,从1.11后都是这种模式,项目根路径下会有一个go.mod

go path模式介绍

之前有个go path模式,已经弃用了,它的包导入,不是从项目路径下开始导入,而是从go path 的src路径下路径下开始导入

go 安装第三方包(以gin包为例)

go语言中的包目前没有同意的存储仓库,因此大部分的go包都是从github中下载的,也可以使用第三方代理下载

ps:github下载速度感人!

主流的代理

配置代理

1、配置局部代理(goland中启用代理)

打开设置界面后,先去找下图的界面是否跟你的界面一样(新版本会不一样),如果一样按照他的操作设置

image

如果你发现自己的界面跟上图的界面不一样,就参考这张图中的配置代理设置(需要手动输入)

image

还有一种设置方式

image

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结点组成的对象就是链表对象。火车的不同车厢之间都是通过挂钩连接的,当两个车厢之间脱钩之后,两个车厢就没有任何关系了。

image

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

请注意,这只是一个简单的链表实现,还有很多方面可以进行改进和优化。