Go的变量类型、Go函数、Go的包、Go的流程控制、Switch关键字

发布时间 2023-04-26 20:18:45作者: yiwufish

GO的变量类型

1.普通类型

1.整形
int   int8   int16   int32   int64

int8 -2的7次方~2的7次方-1     ====》》  一个字节表示(8个比特位)
int16 -2的15次方~2的15次方-1
int32 同理
int64 同理

int 分机器,32位机器是int32  64位机器是int64


uint  uint8  uint16  uint32  uint64
因为不需要负的,所以扩容一倍

uint8 2的8次方-1
uint16 2的16次方 -1 

uint同理


浮点型:表示小数
float32   保留小数点后7位左右
float64   保留小数点后16位左右
不够准确的,带有末尾四舍五入


复数类型  实部和虚部,各自独立运算
complex64 
complex128


rune  byte
rune 是 int32 的别名
byte 是 uint8 的别名   


2.字符串

string

双引号  不能自动换行,要加换行符
反引号  带换行格式

单引号   放一个字符,对应的是ascci码的编码数字


3.布尔类型
只有
true 
false 

空值是false



2.常量

1.一旦定义,值固定了后续不能修改

const 关键字申明定义常量

================
2.作用域范围:

变量重复定义只要不在同一个范围内,可以搞,但是外部定义必须用完整定义或者类型推导
比如
var name string = "jack"
func main() {
	name = "rose"   # 优先用自己作用域的
	fmt.Println(name) 

}

3.同一时间定义多个常量,如果第二个常量不赋值,他的值就是第一个常量的值

3.iota的使用

​ 必须用const定义

​ 有啥用啊?能用来做枚举,但是目前还先不做了解枚举

const (
a = iota  
b          // 1
c         //  2
d         //  3
  
)

只要用了iota,下一行开始就会自增

===================

const (
    a = 10
    b
    c = 15
    d = iota             // d 值是3 
)

类似看索引位置,只要用了iota 就是值为索引值

Go的函数

1.普通函数

​ 注意,Go支持函数写在执行的后面,Python则不行的,因为一个是编译型,一个是解释型

1.无参无返回值
 就很简单的使用
    
2.有参数,无返回值
	需要指定参数类型!!!参数位置定死,关键字传参
func test(a, b int) {

	fmt.Println(a, b)
	
}

调用:
test(1,4)   # test(a=1,b=4)不行
3.有参数,有一个返回值
func test(a,b int) int {
    return a+b
}
res := test(1,5)
    fmt.Println(res)
    
    
4.有参数,有多个返回值
func test(a, b int) (int, int) {

	return a + b, a * b

}

调用:
res, res1 := test(1, 3)
fmt.Println(res)
fmt.Println(res1)

5.调用第四种的函数,不想要某个返回值
 '_' 这玩意是真正的空白!!
res, _ := test(1, 3)
fmt.Println(res)

2.函数高级

1.匿名函数
1.func (){
    ....
}()

加括号直接调用

2.赋值给一个变量--->函数是一种类型---》在go中,函数又称一等公民(可以赋值给变量的都叫一等公民),又叫头等函数,一等函数
func test4() {

	f := func() {
		fmt.Println("我是内层函数")
	}
	f()
}


3.函数的参数不同,是不同的类型
func test4() {

	var f func() = func() {
		fmt.Println("我是内层函数")

	}
	var f1 func(a int) = func(a int) {
		fmt.Println(a)
	}
	fmt.Printf("%T\n", f)
	fmt.Printf("%T", f1)
}

>>>
func()
func(int)    // 不同类型

2.返回值是函数
定义这样一个函数,需要传参一个函数进去,返回两个返回值
func test5(a func()) func(int, int) int {
	a()
	return func(x, y int) int {
		return x + y
	}
}

调用:
func main() {
	f := test5(func() {
		fmt.Println("我是被传入的函数")
	})
	res := f(11, 12)     # 结果是 23
	fmt.Println(res)
}
3.类型重命名——type
1.type Myint int 
	相当于创建了全新的一种类型,不能与不同类型的数据做运算,
2.type Myint = int 
	这个就是重命名,本质还是指向原来的类型

可以看作是深浅拷贝
	
4.可变长参数

​ Go中没有关键字参数,只有可变长

定义一个函数 ,...表示任意长度,可以指定一起的类型
func test6(a ...int) {
	fmt.Println(a)
	fmt.Printf("%T", a)
}

调用:
test6(1, 2, 3, 4, 5, 6, 6, 7, 8)

结果:
[1 2 3 4 5 6 6 7 8]
[]int            
Go中列表叫切片,切片又有很多类型,比如这种,int切片类型

5.defer 延迟调用
可以用来修饰GO语句,会延迟调用,并且以先进后出的原则,最先声明defer的GO语句最后执行

比如:

defer fmt.Println("你好~")
defer fmt.Println("你也好~")
fmt.Println("我本来是最后执行的")
 执行的结果是
    >>>
    我本来是最后执行的
	你也好~
	你好~
	>>>
 
如果涉及到引用,如果是内部引用外部,值按照defer执行时的算
如果是定义的时候就已经把外部某个值传进去,那值按defer执行前的算
比如:
var a = 100
defer func() {
    fmt.Println(a)
}()
a = 99

	该func直接引用a,延迟生效,生效时a已经是99
================================
var a = 100
defer func(i int) {
    fmt.Println(i)
}(a)
a = 99
	该func定义阶段就把a当实参传入,此时a已经被复制进去了,定死了,所以a=100

Go的包

​ go 的包分为:sdk内置包 、自定义包、第三方包

​ 包就是文件夹,这个文件夹下所有的go文件第一行都要声明包,建议就是包的名字,虽然可以自己定声明的名字

1.包的交互

​ 注意,包内部,大写开头,表示导出 变量,函数。。。

​ 同一个包下,名称空间共享,如果重新定义会冲突

​ 同一个文件夹下只能有一个包,意思就是该路径下不同go文件的包不能不一样

​ 一个文件夹下可以再创建新的包,各个文件夹只有层级关系无其他联系

​ 以上组成的模式叫go mod 模式,从1.11后都是这种模式,项目根路径下会有一个go.mod

我们在项目路径下创建一个包,创建一个go文件
比如 fun/happy.go

文件中写点东西
package ggo

var Wohh = 10

func Test(a, b int) int {
	return a + b
}


然后我们去根目录下的其他文件,带有main包的,因为main包才能作为执行文件
package main

import (
	"fmt"
	"go_day01/ggo"           # 会自动识别路径
)

func main() {
	res := ggo.Test(1, 4)
	fmt.Println(res)
	fmt.Println(ggo.Wohh)
}


​ 导入包可以重命名,重命名完成后以后直接用包名点即可

import (
	"fmt"
	xixixi "go_day01/ggo"
)

xixixi.Wohh

2.包的init

​ 可以重复定义

给ggo文件中加入init
func init() {
	fmt.Println("哇,我会自动执行")
}

func init() {
	fmt.Println("哇,我也会自动执行")
}

func init() {
	fmt.Println("哇,我绝对会自动执行")
}

==========================================
只要有main执行了导入这个包的操作,就会执行所有的init,类似python 的 __init__

3.光导入不使用

导入时做成空白 _
import _ "go_day01/ggo"
这样就可以避免go的只要导入必须使用的原则

但是注意,init一样会执行,因为你确实导入了

Go的gin框架

1.下载

官网地址
https://gin-gonic.com/zh-cn/docs/quickstart/

安装
go get -u github.com/gin-gonic/gin      // 要换下源才能快速下载

换源
GOPROXY=https://goproxy.cn,direct
可以局部换
	去go_land   File | Settings | Go | Go Modules 粘贴https://goproxy.cn,direct
或者全局改

2.简单使用

// 程序入口包
package main

// 导入gin框架
import "github.com/gin-gonic/gin"

func main() {
	// gin框架的默认实例
	r := gin.Default()

	// 加载templates目录下的所有HTML模板文件,以供后续渲染使用
	r.LoadHTMLGlob("templates/*")

	// GET请求处理函数,返回JSON数据
	r.GET("/", func(context *gin.Context) {
		context.JSON(200, gin.H{
			"code":    "100",
			"message": "成功",
		})
	})

	// GET请求处理函数,返回HTML模板页面
	r.GET("/index", func(context *gin.Context) {
		// 通过HTML渲染模板文件index.html,并且传入模板变量name和age
		context.HTML(200, "index.html", gin.H{
			"name": "jack",
			"age":  24,
		})
	})

	// 启动HTTP服务器,监听8080端口
	r.Run()
}

都是固定搭配,暂时听个响,然后启动这个文件file,访问浏览器8080端口即可

Go流程控制

1.if条件

固定格式:
注意else必须同行,不能换行下去

if 条件 {
...
} else if 条件 {
...
} else{
...
}

演示:
package main

import "fmt"

func main() {

	a := 200
	if a >= 100 {
		fmt.Println("厉害啊!")
	} else if a >= 150 && a <= 160 {
		fmt.Println("哇太厉害了!")
	} else {
		fmt.Println("啊哦")
	}

}

2.for循环

格式:
for 定义变量 ; 条件 ; 结果 {
    
}
三个都可以省略,但是一般起码有条件摆着,注意分号不能省,结构不能破坏(虽然编辑器会优化,但是习惯要好)
演示:
1.func main() {
	i := 0
	for ; i < 10; i++ {
		fmt.Println(i)
	}

}
2.结果放{}里面也可以的
func main() {
	i := 0
	for i < 10 {
		
		fmt.Println(i)
		i++
	}

}
3.都省,死循环
for {
    xxx
}


上面都是基于索引的循环
================================
这里是基于迭代的循环

func main() {
	s := "jack"
	for i, v := range s {   //range 按字符
		fmt.Println(i)
		fmt.Println(v)   // 这里拿的是字节数字,可以string转 	fmt.Println(string(v))
	}

}

break 和continue
和python一样的

Switch

​ 优雅的替换掉if 和 else

1.case   拿switch后面的值和case的值来比较,如果相同,执行相应的代码,也可以多条件,等于Or关联
func main() {
	a := 100
	switch a {
	case 90:                
		fmt.Println("我是90分")
	case 100:
		fmt.Println("我是一佰昏")

	}

}

2.default 相当于else
func main() {
	a := 101
	switch a {
	case 90:
		fmt.Println("我是90分")
	case 100:
		fmt.Println("我是一佰昏")
	default:
		fmt.Println("都不是哦")
	}

}


3.switch后无条件
func main() {
	a := 101
	switch {
	case a > 90 && a < 100:
		fmt.Println("我是优秀")
	case a > 100:
		fmt.Println("我是超棒")
	default:
		fmt.Println("都不是哦")
	}

}

break和Fallthrough

别的语言中switch 每个case下如果不写break 就会被触发

但是go 默认注入了break ,所以即使第一个条件达成了,第二第三个条件也不会触发


Fallthrough一加,如果该条件触发了,就会无条件执行下一个,就一个哦,不会多


func main() {
	a := 122
	switch {
	case a > 90 && a < 100:
		fmt.Println("我是优秀")
	case a > 100:
		fmt.Println("我是超棒")
		fallthrough
	case a < 60:
		fmt.Println("不行啊")
	default:
		fmt.Println("都不是哦")
	}

}

执行结果:

我是超棒
不行啊

注意

1.Go的那个文件,不是首行写了导入main包吗?如果新建的其他go文件,也是导入这个包,名称空间是共享的
2.Go的类型千奇百怪,函数也能作为类型