Golang基础语法【快速入门】

Go基础语法【快速入门】

一、Go的安装

1.1 Windows系统

我最开始用的Windows系统学的go,但是后来转了Linux

安装方法:

前往Go官网下载安装包(后缀为msi)

或者去Go中文社区下载

下载完运行,一直下一步就可以

在配置Go的一些环境

1.2 Linux系统

同上下载安装包**(tar.gz)**

将安装包移动到/usr/local

$ sudo mv 安装包名称 /usr/local

使用命令解压安装包:

$ tar -zxvf 下载的go安装包名称

配置环境:

环境变量配置文件/etc/profile中添加以下内容:

打开文件命令:

$ sudo vim /etc/profile
# Go PATH
export PATH=$PATH:/usr/local/go/bin

输入----->按i进行编辑,完成后按esc退出编辑,输入:wq退出

让配置文件生效:

$ source /etc/profile

查看Go版本

$ go version

若显示Go版本就表示成功了

1.3 Go Modules和代理

Go Modules是Go语言依赖管理解决方案。

Go.mod是Golang1.11版本新引入的官方包管理工具用于解决之前没有地方记录依赖包具体版本的问题,方便依赖包的管理。

Go.mod其实就是一个Modules,Modules是相关Go包的集合,是源代码交换和版本控制的单元。

一个源代码目录甚至是空目录都可以作为Modules,只要其中包含有go.mod文件

1.3.1 第一步,mod文件字段内容

go.mod是启用了Go moduels的项目所必需的最重要的文件,它描述了当前项目(当前模块)的元信息,每一行都以一个动词开头。目前有以下5个动词

  1. module:用于定义当前项目的模块路径
  2. go:用于设置预期的Go版本。
  3. require:用于设置一个特定的模块版本。
  4. exclude:用于从使用中排除一个特定的模块版本。
  5. replace:用于将一个模块版本替换为另外一个模块版本。
1.3.2 第二步,生成go.mod
# 打开Go modules

go env -w GO111MODULE=on

# 设置GOPROXY 镜像源 用国内的

go env -w GOPROXY=https://goproxy.cn,direct

在go文件夹创建一个hello.go的文件。文件内容如下:

package main

import "fmt"

func main(){
    fmt.Println("Hello World!")
}

在项目根目录生成go.mod文件

$ cd 文件路径
$ go mod init hello(模板名称)
1.3.3 第三步,Go modules常用命令

go get 拉取依赖

# 拉去最新版本
$ go get //地址
# 拉取指定版本
$ go get //地址+版本号
# 更新所有依赖
$ go get -u
# 整理现有的依赖
$ go mod tidy
# 查看现有的依赖结构
$ go mod graph
# 生成go.mod文件(唯一可以生成go.mod文件的子命令)
$ go mod init
# 编辑go.mod文件
$ go mod edit
# 导出现有的所有依赖
$ go mod vendor
# 校验一个模块是否被篡改过
$ go mod verify

二、基础语法

2.1第一个go程序

在控制台打印输出hello world

package main
import "fmt"
func main(){
    fmt.Println("hello world")
}
2.1.1 将go程序编译为可执行文件

Windows 系统编译为.exe文件

Linux 系统为二进制文件

2.1.1.1 编译单个文件
# 进入需要编译的文件目录
$ cd 目录地址
# 编译文件
$ go build XXX.go
2.1.1.2 编译整个项目
# 进入项目更目录
$ cd 地址
# 进行编译
$ go build

2.2 变量

go 里面 定义的变量必须要用,如果你不想用可以使用_为变量名

2.2.1 匿名变量
package main

import "fmt"

func foo() (int, int) {
	return 1, 2
}

//匿名函数用于后面函数 固定返回两个值,但是我们只需要一个数据  可以使用匿名函数将数值隐下去
/*
用_作为匿名函数

*/
func main() {
	var a, _ = foo()
	fmt.Println(a)
}

2.2.2 变量定义
// go变量定义
package main

import (
	"fmt"
	"time"
)

var x = "我是全局变量"

func name() {
	fmt.Println(x, ",这是name函数调用")
}
func bar() {
	fmt.Println(x, ",这是bar函数调用")
}
func main() {
	bar()
	name()
	//	声明一个变量 var 变量名 = 值
	var one = 1
	var two = 2
	var zreo int
	fmt.Println(zreo) //声明未赋值  默认是0
	fmt.Println(one + two)
	//	数据类型声明可以不用
	var name string = "张天昊"
	var ts bool = true
	fmt.Println(name, ts)
	zreo = 10
	fmt.Println(zreo + 1)
	zreo = 40
	fmt.Println(zreo + 2)
	zreo = 30
	fmt.Println(zreo + 3)
	//	go 有一个自己的回收机制

	//	同时声明多个变量
	var (
		old int    //0
		ssq string //""
		tf  bool   //false
	)
	//old = 10
	//ssq = "ssq"
	//tf = true
	fmt.Println(old, ssq, tf)
	sums()

	//	声明并且赋值的简洁写法  只能在函数内部使用
	name2 := "张"
	fmt.Println(name2)
	all()
	time.Sleep(5 * time.Second)
}
func sums() {
	var name = "函数sums"
	fmt.Println(name)
}
func all() {
	//	一行声明多个变量
	var name, age, isMarild = "zhang", 23, false
	fmt.Println(name, age, isMarild)
}

2.3 值拷贝

这是go语言的一个特性,与python等动态语言不一样

go中每个变量是不同的地址

package main

import "fmt"

func main() {
	//与python不同   python一变则全变
	//go中为拷贝 是完全不同的内存地址
	var x = 10
	var y = x
	x = 20
	//x= 20 y= 10
	fmt.Println("x=", x, "y=", y)
	sum()
}

func sum() {
	var a = 1 + 1
	var b = a
	var c = a * b
	fmt.Println(a, b, c)
}

2.4 基本数据类型

go语言中数据类型分为了**基本数据复杂数据类型**

数据类型取值范围
booltrue 或 false
string任何UTF-8编码字符串
int有符号整数,取值范围为 -2147483648 至 2147483647
int8有符号8位整数,取值范围为 -128 至 127
int16有符号16位整数,取值范围为 -32768 至 32767
int32有符号32位整数,取值范围为 -2147483648 至 2147483647
int64有符号64位整数,取值范围为 -9223372036854775808 至 9223372036854775807
uint无符号整数,取值范围为 0 至 4294967295
uint8无符号8位整数,取值范围为 0 至 255
uint16无符号16位整数,取值范围为 0 至 65535
uint32无符号32位整数,取值范围为 0 至 4294967295
uint64无符号64位整数,取值范围为 0 至 18446744073709551615
uintptr无符号整数,用于存储一个指针
float3232位浮点数
float6464位浮点数
complex64由32位实数和32位虚数组成的复数
complex128由64位实数和64位虚数组成的复数
2.4.1 转义符
\反斜杠用于转义下一个字符
单引号用于在单引号括起的字符字面值中表示单引号字符
"双引号用于在双引号括起的字符串字面值中表示双引号字符
\a蜂鸣声符
\b退格符,将当前位置移到前一列
\f换页符,将当前位置移到下页开头
\n换行符,将当前位置移到下一行开头
\r回车符,将当前位置移到本行开头
\t水平制表符,将当前位置移到下一个制表符位置
\v垂直制表符,将当前位置移到下一垂直制表符位置
\xhh十六进制转义符,其中 hh 代表一个或多个表示十六进制值的数字
2.4.2 占位符
占位符用途
%v根据变量的值来输出
%+v在 %v 基础上,对结构体、切片等类型,将字段名与值一起输出
%#v输出值的 Go 语法表示方式
%T输出变量的类型
%%输出百分号本身,不进行任何格式化操作
%t输出 bool 类型变量
%d or %i输出十进制整数
%o输出八进制数
%x or %X输出十六进制数
%U输出 Unicode 字符集格式
%e or %E输出浮点型数据的科学计数法表示
%f输出浮点型数据的标准计数法表示
%q输出双引号引起来的字符串
%s输出字符串
2.4.3整型
package main

import (
	"fmt"
	//reflect 为打印数据类型的包
	"reflect"
)

func main() {

	//整形
	/*
		int8 : -127~127   \\\\\2的8次方个数
		uint8 : 0~255
		等等
		int  在32位系统上就用的int32
		int  在64位系统上就用的int64
		int8: 一个字节  [-127~128]
		uint8 : 从0开始[0~255]
	*/
	var s int
    var i int8
    ....
}
2.4.4 浮点型
package main

import (
	"fmt"
    "reflect"
)
func main(){
    /*
		浮点型

		float类型
		float类型分为float32和float64两种类型,这两种浮点型数据格式遵循 IEEE 754 标准。
		单精度浮点数占用4个字节(32位)存储空间来存储一个浮点数。而双精度浮点数使用 8个字节(64位)存储空间来存储一个浮点数。
		单精度浮点数最多有7位十进制有效数字,如果某个数的有效数字位数超过7位,当把它定义为单精度变量时,超出的部分会自动四舍五入。双精度浮点数可以表示十进制的15或16位有效数字,超出的部分也会自动四舍五入。
		浮点类型默认声明为float64。
	*/
	var f1 float32
	f1 = 3.15487464
	//reflect.TypeOf  打印数据类型
	fmt.Println(f1, reflect.TypeOf(f1))
}
2.4.5 布尔型
package main

import (
	"fmt"
    "reflect"
)
func main(){
	/*
		布尔类型
		布尔类型是最基本数据类型之一,只有两个值:true和false,分别代表逻辑判断中的真和假,主要应用在条件判断中
	*/
	var b bool // 声明b是一个布尔类型
	b = true
	b = false // 该类型只有true和false两个值,分别代表真假两种状态
	fmt.Println(b, reflect.TypeOf(b))

	fmt.Println(1 == 1) // 比较运算符的结果是一个布尔值
	// fmt.Println(1 == "1") // 报错,mismatched types不能比较
	fmt.Println(3 > 1)

	var name = "yuan"
	var b2 = name == "rain"
	//false ****
	fmt.Println(b2)
}
2.4.6 字符类型
package main

import (
	"fmt"
    "reflect"
)
func main(){
/*
					字符串
				字符串是最基本也是最常用的数据类型,是通过双引号将多个字符按串联起来的一种数据,用于展示文本
			单引号只能标识字符
		    注意:

		        索引从零开始计数
		        go语言不支持负索引
	*/
	var s = "hello zhang"
	fmt.Println(s)

	// (1)索引取值 slice[index]
	a := s[2]
	fmt.Println(string(a))

	// (2)切片取值slice[start:end], 取出的元素数量为:结束位置 - 开始位置;
	b1 := s[2:5] //
	fmt.Println(b1)
	b2 := s[0:] // 当缺省结束位置时,表示从开始位置到整个连续区域末尾;
	fmt.Println(b2)
	b3 := s[:8] // 当缺省开始位置时,表示从连续区域开头到结束位置;
	fmt.Println(b3)

	// (3)字符串拼接
	var s1 = "hello"
	var s2 = "zhang"
	var s3 = s1 + s2 // 生成一个新的字符串
	fmt.Println(s3)
}
2.4.7 进制转换
package main

import (
	"fmt"
)
func main(){
/*
		进制转换
	*/
	//	十进制转化
	var n int = 10
	//printf 传输数据进去
	fmt.Printf("%d \n", n) //%d  表示十进制
	fmt.Printf("%o \n", n) // 占位符%o表示八进制
	fmt.Printf("%b \n", n) //占位符%b表示二进制
	fmt.Printf("%x \n", n) //占位符%x表示十六进制
	// 八进制转化
	var b int = 020
	fmt.Printf("%o \n", b) // 20
	fmt.Printf("%d \n", b) // 16
	fmt.Printf("%x \n", b) // 10
	fmt.Printf("%b \n", b) // 10000
	// 十六进制转化
	var c = 0x12
	fmt.Printf("%d \n", c) // 18
	fmt.Printf("%o \n", c) // 22
	fmt.Printf("%x \n", c) // 12
	fmt.Printf("%b \n", c) // 10010
}

2.5 字符串的常用方法

package main

import (
	"fmt"
	"reflect"
	"strings"
)

/*

方法 	介绍
len(str) 	求长度
strings.ToUpper,strings.ToLower 	生成一个新的全部大写的字符串,生成一个新的全部小写的字符串
strings.ReplaceAll 	生成一个新的原字符串被指定替换后的字符串
strings.Contains 	判断是否包含
strings.HasPrefix,strings.HasSuffix 	前缀/后缀判断
strings.Trim、 	去除字符串两端匹配的内容
strings.Index(),strings.LastIndex() 	子串出现的位置
strings.Split 	分割,将字符串按指定的内容分割成数组
strings.Join(a[]string, sep string) 	join操作,将数组按指定的内容拼接成字符串

*/

func main() {
	//action
	action()
}
func allstring() {
	var a string
	a = "hello,Zhang,tian,hao"
	//获取字符串长度
	fmt.Println(len(a))
	//	一个全部大写的字符串
	fmt.Println(strings.ToUpper(a))
	//全部小写
	fmt.Println(strings.ToLower(a))
	//	判断是否包含
	fmt.Println(strings.Contains(a, "tianhao"))
	//前缀判断
	fmt.Println(strings.HasPrefix(a, "zth"))
	//后缀判断
	fmt.Println(strings.HasSuffix(a, "hao"))
	//	是否包含
	fmt.Println(strings.Contains(a, "tian"))
	//	去除字符串两端匹配的内容
	s := strings.Trim(a, "o")
	fmt.Println(s)
	//子串出现的位置
	fmt.Println(strings.Index(a, "Z")) //没有找到就返回-1
	//最后一次出现的位置
	fmt.Println(strings.LastIndex(a, "o"))
	//分割,将字符串按指定的内容分割成数组
	a2 := strings.Split(a, ",")
	//fmt.Println(reflect.TypeOf(a2))
	fmt.Println(a2)
	//将数组拼接成字符串
	var set = strings.Join(a2, "-")
	fmt.Println(set, "\n", reflect.TypeOf(set))
}
func action() {
	s := "mysql … -u root -p 123"
	uindex := strings.Index(s, "-u")
	pindex := strings.Index(s, "-p")
	user := s[uindex+3 : pindex-1]
	psd := s[pindex+3:]
	fmt.Println("用户名为", user, "密码为", psd)
}

2.6 数据类型转换

package main

import (
	"fmt"
	"reflect"
	"strconv"
)

func main() {
	//(1)整型之间的转换 int8 int16
	var x int8 = 10
	var y int16 = 20
	fmt.Println(x + int8(y))
	// (2)字符串与整型之间的转换 strconv库
	var agestr = "32"
	//var name = 12
	//字符串转整型
	var age, _ = strconv.Atoi(agestr)
	fmt.Println(age)
	//fmt.Println("err: ", err) // <nil>空对象
	price := 100
	//整形转字符
	price_str := strconv.Itoa(price)
	fmt.Println(price_str, reflect.TypeOf(price_str))

	//strconv parse系列函数
	//字符串转整型 base进制   bitSize是比特位 8---int8
	ret, _ := strconv.ParseInt("28", 10, 8)
	fmt.Println(ret, reflect.TypeOf(ret))
	//字符串转换为浮点型
	floats, _ := strconv.ParseFloat("3.1415926", 64)
	fmt.Println(floats, reflect.TypeOf(floats))
	//字符串转换为布尔值
	b, _ := strconv.ParseBool("0")
	b1, _ := strconv.ParseBool("-1")
	b2, _ := strconv.ParseBool("true")
	b3, _ := strconv.ParseBool("T")
	fmt.Println(b, b1, b2, b3)
}

2.7 运算符

运算符描述
算数运算符用于执行基本的数学运算,如加法、减法、乘法和除法
+加法运算符,将两个数相加
-减法运算符,从第一个数中减去第二个数
*乘法运算符,将两个数相乘
/除法运算符,将第一个数除以第二个数
%取模运算符,返回第一个数除以第二个数的余数
自增和自减运算符自增或自减运算符用于递增或递减变量的值
++自增运算符,将变量的值加一
自减运算符,将变量的值减一
比较运算符用于比较两个值之间的关系,返回一个布尔值
==等于运算符,如果两个值相等则返回 true,否则返回 false
!=不等于运算符,如果两个值不相等则返回 true,否则返回 false
>大于运算符,如果左边的值大于右边的值则返回 true,否则返回 false
<小于运算符,如果左边的值小于右边的值则返回 true,否则返回 false
>=大于等于运算符,如果左边的值大于等于右边的值则返回 true,否则返回 false
<=小于等于运算符,如果左边的值小于等于右边的值则返回 true,否则返回 false
逻辑运算符用于执行逻辑运算,如AND、OR、和NOT
&&逻辑 AND 运算符,两个操作数都为 true 时才返回 true,否则返回 false
||逻辑 OR 运算符,两个操作数有一个为 true 时返回 true,否则返回 false
!逻辑 NOT 运算符,如果条件为 true 则返回 false,否则返回 true
位运算符用于执行二进制位运算,例如 按位与、按位或、按位异或等
&按位 AND 运算符,参与运算的两个值都为 1 时才返回 1,否则返回 0
|按位 OR 运算符,参与运算的两个值有一个为 1 时就返回 1,否则返回 0
^按位异或运算符,参与运算的两个值只有一个为 1 时才返回 1,否则返回 0
<<左移运算符,将第一个操作数的二进制位向左移动第二个操作数指定的位数
>>右移运算符,将第一个操作数的二进制位向右移动第二个操作数指定的位数
赋值运算符用于将一个值赋给一个变量或表达式
=简单赋值运算符,将右边表达式的值赋给左边的变量
+=加法赋值运算符,等价于 a = a + b
-=减法赋值运算符,等价于 a = a - b
*=乘法赋值运算符,等价于 a = a * b
/=除法赋值运算符,等价于 a = a / b
%=取余赋值运算符,等价于 a = a % b
<<=左移赋值运算符,等价于 a = a << b
>>=右移赋值运算符,等价于 a = a >> b
&=按位 AND 赋值运算符,等价于 a = a & b
package main

import "fmt"

func main() {
	// 和python运算符一样

	//计算一个数是为奇数还是偶数
	x, y := 10, 20
	fmt.Println(x%2 == 0, y)

	//关系运算符 与python相同 == != >= <= 返回布尔值
	fmt.Println(x >= y)
	//逻辑运算符
	//与或非运算
	/*
		与&&: 真真-真,真假-假,假假-假 ,
		或||: 真或真-真,真或假为真,假或假为假
		非运算 !:非真为假,非假为真  取反
	*/
	fmt.Println(true && false)
	fmt.Println(true || false)
	fmt.Println(!true || false)
	//database:root 123
	username := "zhang"
	password := 123
	fmt.Println(username == "root" && password == 123)
	/*
		赋值运算
		和python一样
	*/
	var a = 12
	a += 1
	fmt.Println(a)
	var b = 10
	//自加一
	b++
	fmt.Println(b)
	//优先级
	var q, w, z = 1, 2, 3
	fmt.Println(q, w, z)
	var t = q + w
	fmt.Println(t)
}

2.8 输入输出函数

2.8.1 输出函数

go中常用的输入输出函数,在fmt包中

package main

import "fmt"

func main() {
	//输出函数
	//print println
	var name, age = "yuan", 32
	fmt.Println("hello world")
	fmt.Println(name)
	fmt.Println(age)
	fmt.Println("姓名:", name, "年龄", age)
	//fmt.Print(name)
	//fmt.Print(age)
	var isMarried = false
	fmt.Printf("姓名:%s,年龄:%d,婚否:%t\n", name, age, isMarried)
	//sprintf:
	s := fmt.Sprintf("姓名:%s,年龄:%d,婚否:%t", name, age, isMarried)
	fmt.Println(s)
}

2.8.2 输入函数
package main

import (
	"fmt"
	"strings"
)

func main() {
	//输入函数 IO函数
	scan()
}
func action() {
	var (
		birth string
	)
	fmt.Println("输入生日格式如:1988-3-16")
	fmt.Scan(&birth)
	birthslice := strings.Split(birth, "-")
	fmt.Printf("您的生日是%s年-%s月-%s日", birthslice[0], birthslice[1], birthslice[2])

}
func scan() {
	//(1)fmt.scan
	//var name string
	//var age int
	//fmt.Scan(&name, &age)
	//fmt.Println(name, age)
	//(2)fmt.scanln

	//(3)fmt.scanf  按照指定的格式输入
	var a, b int
	fmt.Scanf("%d+%d", &a, &b)
	fmt.Println(a + b)
}
func action2() {
	var name string
	fmt.Println("请输入一个英文名: ")
	fmt.Scan(&name)
	var b = (strings.HasPrefix(name, "a")) || (strings.HasPrefix(name, "A"))
	fmt.Println(b)
}

2.9 流程控制语句

2.9.1 if语句
满足条件
不满足条件
满足条件
不满足条件
开始
是否满足条件?
执行语句1
是否满足另一条件?
执行语句2
执行语句3
结束
package main

import "fmt"

func main() {
	twoIf()
}
func twoIf() {
	//双分支if else
	var (
		passworld any
		input     string
	)
	passworld = "123"
	fmt.Println("输入密码:")
	fmt.Scan(&input)
	if passworld == input {
		fmt.Println("密码正确")
	} else {
		fmt.Println("密码错误")
	}
}

多分支

package main

import "fmt"

func main() {
	weeks()
}

func scanres() {
	//判断成绩
	var scanre int
	fmt.Println("输入你的成绩")
	fmt.Scan(&scanre)
	if scanre > 100 || scanre < 0 {
		fmt.Println("输入数字不合法")
	} else if scanre >= 90 {
		fmt.Println("优秀")
	} else if scanre >= 70 {
		fmt.Println("良好")
	} else if scanre >= 60 {
		fmt.Println("及格")
	} else {
		fmt.Println("不及格")
	}
}
func weeks() {
	var week int
	fmt.Println("输入1-7的数字")
	fmt.Scan(&week)
	if week == 1 {
		fmt.Printf("星期%d", week)
	} else if week == 2 {
		fmt.Printf("星期%d", week)
	} else if week == 3 {
		fmt.Printf("星期%d", week)
	} else if week == 4 {
		fmt.Printf("星期%d", week)
	} else if week == 5 {
		fmt.Printf("星期%d", week)
	} else if week == 6 {
		fmt.Printf("星期%d", week)
	} else if week == 7 {
		fmt.Printf("星期%d", week)
	} else {
		fmt.Println("非法输入")
	}
}

2.9.2 switch语句
case 1
case 2
case 3
default
开始
选择变量值
执行语句1
执行语句2
执行语句3
执行默认语句
结束
package main

import "fmt"

func main() {
	weeks()
}

func weeks() {

	switch week {
	case 1:
		fmt.Printf("星期%d", week)
	case 2:
		fmt.Printf("星期%d", week)
	case 3:
		fmt.Printf("星期%d", week)
	case 4:
		fmt.Printf("星期%d", week)
	case 5:
		fmt.Printf("星期%d", week)
	case 6:
		fmt.Printf("星期%d", week)
	case 7:
		fmt.Println("星期日")
	default:
		fmt.Println("非法输入")
	}
}

2.9.3 流程控制语句练习

星座判断

package main

import "fmt"

func main() {
	var (
		month   int
		day     int
		xingZuo string
	)
	fmt.Println("输入月和日")
	fmt.Scan(&month, &day)
	if month > 12 && day > 31 && day < 1 {
		fmt.Println("输入有误")
	} else {
		switch month {
		case 1:
			if day >= 1 && day <= 19 {
				xingZuo = "摩羯座"
			} else {
				xingZuo = "水瓶座"
			}
		case 2:
			// 日判断
			if day >= 1 && day <= 18 {
				xingZuo = "水瓶座"
			} else {
				xingZuo = "双鱼座"
			}
		case 3:
			// 日判断
			if day >= 1 && day <= 20 {
				xingZuo = "双鱼座"
			} else {
				xingZuo = "白羊座"
			}
		case 4:
			// 日判断
			if day >= 1 && day <= 19 {
				xingZuo = "白羊座"
			} else {
				xingZuo = "金牛座"
			}
		case 5:
			// 日判断
			if day >= 1 && day <= 20 {
				xingZuo = "金牛座"
			} else {
				xingZuo = "双子座"
			}
		case 6:
			// 日判断
			if day >= 1 && day <= 21 {
				xingZuo = "双子座"
			} else {
				xingZuo = "巨蟹座"
			}
		case 7:
			// 日判断
			if day >= 1 && day <= 22 {
				xingZuo = "巨蟹座"
			} else {
				xingZuo = "狮子座"
			}
		case 8:
			// 日判断
			if day >= 1 && day <= 22 {
				xingZuo = "狮子座"
			} else {
				xingZuo = "处女座"
			}
		case 9:
			// 日判断
			if day >= 1 && day <= 22 {
				xingZuo = "处女座"
			} else {
				xingZuo = "天秤座"
			}
		case 10:
			// 日判断
			if day >= 1 && day <= 23 {
				xingZuo = "天秤座"
			} else {
				xingZuo = "天蝎座"
			}
		case 11:
			// 日判断
			if day >= 1 && day <= 22 {
				xingZuo = "天蝎座"
			} else {
				xingZuo = "射手座"
			}
		case 12:
			// 日判断
			if day >= 1 && day <= 21 {
				xingZuo = "射手座"
			} else {
				xingZuo = "摩羯座"
			}
		default:
			fmt.Println("输入的月份有问题")
		}

		fmt.Println("您的星座是:", xingZuo)
	}
}

2.10 循环语句

在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。一组被重复执行的语句称之为循环体,
能否继续重复,决定循环的终止条件。

与其它主流编程语言不同的的是,Go语言中的循环语句只支持 for 关键字,而不支持 whiledo-while 结构。

条件成立
不是最后一次
是最后一次
开始
forLoop
检查条件
执行语句
检查是否为最后一次循环
更新循环变量
结束
2.10.1 for循环
package main

import "fmt"

func main() {
	//var a = 100
	//for a > 0 {
	//	a--
	//	fmt.Println(a)
	//}
	//	三要素for循环
	/*
		var a = 100//初始语句
		a > 0//条件语句
		a--//步进语句
	*/
	//for count := 0; count < 10; count++ {
	//	fmt.Println(count)
	//}
	var s = 0
	for i := 1; i <= 100; i++ {
		s += i
	}
	fmt.Println(s)
}

2.10.2循环分支嵌套
package main

import "fmt"

func main() {
	//for_switch()
	//if_for()
}
func for_if() {
	for count := 1; count <= 100; count++ {
		if count%2 == 0 {
			fmt.Println("偶数有:", count)
		}
	}
}

func if_for() {
	var num int
	fmt.Println("(1)从大到小,(2)从小到大")
	fmt.Scan(&num)
	if num == 1 {
		for count := 1; count <= 100; count++ {
			fmt.Println(count)
		}
	} else if num == 2 {
		for count := 100; count <= 1; count-- {
			fmt.Println(count)
		}
	} else {
		fmt.Println("输入不规范")
	}
}
2.10.3 退出循环
package main

import "fmt"

func main() {
	//for_switch()
}

func breaks() {
	for i := 0; i < 10; i++ {
		if i == 6 {
			break
		}
		fmt.Println(i)
	}
	fmt.Println("退出了循环")
}
func for_switch() {
	var num int
	fmt.Println(`
		1,普通攻击
		2,技能攻击
		3,逃跑
		4,求助
		5,退出
		`)

	for true {
		fmt.Scan(&num)
		if num == 5 {
			break
		}
		switch num {
		case 1:
			fmt.Println("普通攻击")
		case 2:
			fmt.Println("技能攻击")
		case 3:
			fmt.Println("逃跑")
		case 4:
			fmt.Println("求助")
		default:
			fmt.Println("输入有误")
		}
	}
}
func continues() {
	for count := 0; count < 10; count++ {
		if count == 6 {
			continue
		}
		fmt.Println("这是continue", count)
	}
}
func action() {
	for i := 1; i <= 100; i++ {

	}
}

2.11 复杂数据类型

以下为go语言常见复杂数据类型

数据类型描述
数组存储具有相同数据类型的固定尺寸元素的连续集合
指针通过数据地址取值,或者操作地址
切片动态大小的、可变长度的序列,可以看作是对数组的抽象封装
映射(Map)一种无序的键值对的集合,其中所有的键都是唯一的
结构体用于表示一组不同类型的数据的集合,通过一个唯一的名字来区分不同的字段
接口一种类型,指定了一组方法的集合,可以实现多态的效果
通道(Channel)一种数据类型,用于在不同goroutine之间传递数据,类似于管道(pipe)
2.11.1 指针类型

go的指针只有两个操作
& 变量 取址符 返回变量所在的地址

package main

import (
	"fmt"
	"reflect"
)

func main() {
	//获取地址  &
	//var x = 10
	//fmt.Printf("赋值前x的地址%p\n", &x)
	//x = 100
	//fmt.Printf("赋值后的地址%p\n", &x)
	var x = 10                          //x称为整型变量
	fmt.Println(&x, reflect.TypeOf(&x)) //地址是一个 *int(整型指针类型)
	//地址赋值
	var p *int
	p = &x // 也可以var p =&x
	fmt.Println(p, &p)

	//取值操作 :   *指针变量
	fmt.Println(*p, reflect.TypeOf(*p))
	*p = 100
	fmt.Println(x)

	//var a = 1
	//var b = a //值拷贝
	//b = 100   //不会影响a

	//	b影响a,a影响b(通过指针来实现)
	//var b = &a
	a = 102
	//*b = 100
	//fmt.Println(*b)
	//指针案例3
	var a = 100
	var b = &a
	var c = &b
	**c = 200
	fmt.Println(a)
}

2.11.1.1 new函数
package main

import "fmt"

func main() {
	//指针属于引用类型
	// 引用类型 当声明未赋值之前是没有开辟空间的,即没有默认值
	// 要用new一个(类型)
	var a = new(int)
	*a = 10
	fmt.Println(*a)
}

2.11.2 数组
2.11.2.1 数组的声明
// 数组的声明
var arr [5]int
fmt.Println(arr) //[0 0 0 0 0]
2.11.2.2 数组赋值
package main

import "fmt"

func main() {
	// 数组的声明
	var arr [5]int
	fmt.Println(arr) //[0 0 0 0 0]
	//赋值  数组[索引]
	fmt.Println(arr[0])
	fmt.Println(arr[1])
	fmt.Println(arr[2])
	//索引赋值
	arr[0] = 25
	fmt.Println(arr)
	arr[1] = 26
	arr[2] = 27
	arr[3] = 28
	fmt.Println(arr) //[25 26 27 28 0]

	// 数组的声明并赋值
	var names = [3]string{"ran", "zhang", "shi"}
	fmt.Println(names)
	var age = [3]int{1, 2, 3}
	fmt.Println(age)

	//	省略长度赋值
	var name = [...]string{"ran", "zhang", "shi", "jjj", "aaa"}

	fmt.Println(name)
	//索引赋值
	var name1 = [...]string{0: "zhang", 1: "shi"}
	fmt.Println(name1)
	//go len函数 :计算容器长度
	fmt.Println(len(name))
}
2.11.2.3数组操作
2.11.2.3.1索引操作
var names = [3]string{"yuan", "rain", "alvin"}
//索引操作
fmt.Println(names[2])
names[2] = "Rain"
fmt.Println(names)
2.11.2.3.2切片操作
var arr = [...]int{11, 12, 13, 45, 75, 64, 78, 66, 54}
s := arr[0:3]
fmt.Println(s, reflect.TypeOf(s)) //[11 12 13]  []int
s1 := arr[1:]
fmt.Println(s, reflect.TypeOf(s)) //[11 12 13]  []int
s2 := arr[:3]
fmt.Println(s, reflect.TypeOf(s)) //[11 12 13]  []int
s3 := arr[2:4]
fmt.Println(s, reflect.TypeOf(s)) //[11 12 13]  []int
fmt.Println(s1, s2, s3)
2.11.2.3.3 遍历数组
var arr2 = [...]int{1, 2, 3, 4, 5}
for i, i2 := range arr2 {
    //  相当于python中的en...函数
    // i为下标 i2为数据
    fmt.Println(i, i2)
}
fmt.Println("======================================================================")
//用for三要素提取
for i := 0; i < len(arr2); i++ {
    fmt.Println(i, arr2[i])
}
2.11.2.3 切片

切片是对数组的引用

var a = [5]int{1, 2, 3, 4, 5}
var slice = a[:] //起始地址 长度 容量(cap)
fmt.Println(len(slice), cap(slice))

var slice2 = a[:2]
fmt.Println(len(slice2), cap(slice2))
newSlicec := slice[1:3]
newSlicec[1] = 1000 // [1 2 1000 4 5]
fmt.Println(a)
fmt.Println(slice) // [1 2 1000 4 5]
fmt.Println(slice2)
2.11.2.3.1 声明切片
// 直接声明切片
//arr := [5]int{10,11,12,13,14}
//s:=arr[:]
var s = []int{10, 11, 12, 13, 14}
fmt.Println(s)
s1 := s[1:4]
fmt.Println(len(s1), cap(s1))
s2 := s[3:]
fmt.Println(len(s2), cap(s2))
s3 := s1[1:2]
fmt.Println(len(s3), cap(s3))

示例:

func action() {
	var a = [...]int{1, 2, 3, 4, 5, 6}
	a1 := a[0:3]
	a2 := a[0:5]
	a3 := a[1:5]
	fmt.Println(a1)
	fmt.Println(a2)
	fmt.Println(a3)
}
2.11.2.3.2 make函数
package main

import (
	"fmt"
)

func main() {
	//var s []int
	//初始化创建空间       10为容量
	var s = make([]int, 5, 10)
	fmt.Println(len(s), cap(s))
	fmt.Println(s)
	s[0] = 100
	fmt.Println(s)
}

2.11.2.4 map类型

相当于python的字典类型
在go中叫做map类型

  1. 先声明后赋值

    c := make(map[string]string)
    c["name"] = "zhang"
    c["age"] = "18"
    fmt.Println(c)
    
  2. 直接声明赋值,

    info := map[string]string{"name": "yuan", "age": "20", "city": "China"}
    
  3. map增删改查

    //查
    info := map[string]string{"name": "yuan", "age": "20", "city": "China"}
    fmt.Println(info)
    Map()
    //改,增
    info2 := map[string]string{"name": "yuan", "age": "18", "gender": "male"}
    m2 := Map02(info2)
    fmt.Println(m2)
    //	删
    m3 := Map03(info2)
    fmt.Println(m3)
    
  4. map容量

    //	map容量
    m := make(map[string]float32, 100)
    m4 := Map04(m)
    fmt.Println(m4)
    
  5. map的综合应用

    func Map() {
    	//	map增删改查
    	//	通过key访问  查
    	info := map[string]string{"name": "yuan", "age": "18", "gender": "male"}
    	val := info["name"]
    	val, is_exist := info["name"] // 判断某个键是否存在map数据中
    	if is_exist {
    		fmt.Println(val)
    		fmt.Println(is_exist)
    	} else {
    		fmt.Println("键不存在!")
    	}
    	//循环访问所有键值
    	for s, s2 := range info {
    		fmt.Println(s, s2)
    	}
    	noSortMap := map[int]int{
    		1: 1,
    		2: 2,
    		3: 3,
    		4: 4,
    		5: 5,
    		6: 6,
    	}
    	//range顺序随机
    	for i, i2 := range noSortMap {
    		fmt.Println(i, i2)
    	}
    }
    func Map02(s map[string]string) map[string]string {
    	s["height"] = "180cm" // 键不存在,则是添加键值对
    	s["age"] = "22"       // 键存在,则是更新键的值
    	return s
    	//	利用函数写的map02输入map类型 返回map类型
    }
    func Map03(s map[string]string) any {
    	//删
    	delete(s, "name")
    	return s
    }
    func Map04(s map[string]float32) any {
    	//	容量
    	return len(s)
    }
    func Map05() {
    	//	map的灵活运用
    	data := map[string][]string{"hebei": []string{"廊坊市", "石家庄", "邯郸"}, "beijing": []string{"朝阳", "丰台", "海淀"}}
    	// 打印河北的第二个城市
    	// 循环打印每个省份的名字和城市数量
    	// 添加一个新的省份和城市的key-value
    	// 删除北京的key-value
    	s := data["hebei"][1]
    	fmt.Println("河北的第二个城市", s)
    	for s2, _ := range data {
    		for _, s3 := range data[s2] {
    			fmt.Println(s2, len(data[s2]), s3)
    		}
    
    	}
    	//ss := map[string][]string{"sicuan": {"meishan", "chengdu"}}
    	//fmt.Println(ss)
    	var zz = []string{"眉山", "成都"}
    	data["chengdu"] = zz
    	fmt.Println(data)
    	delete(data, "beijing")
    	fmt.Println(data)
    }
    
2.11.2.5 map底层原理
  1. Go语言中的Map基本数据结构是一张哈希表,其中每个哈希表的元素是一个桶(Bucket

    Map
    Bucket1
    Bucket2
    Bucket3
  2. 桶(Bucket)是一个包含一些键值对的可拓展数组(slicemap),keyvalue都占用8个字节的空间。

    Bucket
    KeyValue
    KeyValue
    KeyValue
    KeyValue
    KeyValue
  3. 当我们使用Key在Map中存储或获取值时,Go语言中的Map会自动进行哈希计算以获取桶索引,然后在对应的桶中查找对应的值。

    Map
    Key1
    Key2
    Index1
    Index2
    Bucket1
    KeyValue
    Value
    Hash
    Get Result
    Result不存在

需要注意的是,Go语言中的Map底层实现可以随着版本、编译器和运行环境等因素的不同而略有差异。但是在任何情况下,Map都会使用基于哈希表和桶的底层实现机制来实现其存储和查找功能。

2.11.2.6 append函数

append 追加值,给切片追加,在后面追加数据

package main

import "fmt"

func main() {
	var s []int
	//append 追加值,给切片追加,在后面追加数据
	s1 := append(s, 1)
	fmt.Println(s1)
	s2 := append(s1, 2, 3, 4)
	fmt.Println(s2)

	var t = []int{2, 3, 4}
	t1 := append(t, 1)
	fmt.Println(t1)

	var s4 = make([]int, 3, 10) //初始化完,[0 0 0]
	s5 := append(s4, 100)
	fmt.Println(s5) //[0 0 0 100]
	//Append()
	var c = 255
	fmt.Println(c >> 10)
}

append 底层原理(面试题)

func Append() {
	//append 重新开辟内存
	var a1 = make([]int, 2, 10)
	a2 := append(a1, 1, 23, 4)
	fmt.Println(a1)
	fmt.Println(a2)
	//[0 0]
	//[0 0 1 23 4]
	//因为a1空间为2,所以给他添加3个内容时,append会重新开辟内存,

}
2.11.3 defer 语句
package main

import "fmt"

func cele(index string, a, b int) int {
	res := a + b
	fmt.Println(index, a, b, res)
	return res
}

/*
defer 注册要延迟执行函数时,要先确定他所有参数的值
defer 分为两个顺序--->注册顺序和执行顺序
先注册:
	defer cele("AA", x, cele("A", x, y))
	defer cele("BB", x, cele("B", x, y))
最后执行:
	defer cele("BB", x, cele("B", x, y))
	defer cele("AA", x, cele("A", x, y))
1、cele("A",1,2)  返回3
2、cele("B",10,2)  返回12
3、cele("BB",10,12) 返回22
4、cele("AA",1,3) 返回4

代码执行结果是:
A 1 2 3
B 10 2 12
BB 10 12 22
AA 1 3 4

*/

func main() {
	x, y := 1, 2
	defer cele("AA", x, cele("A", x, y))
	x = 10
	defer cele("BB", x, cele("B", x, y))
	y = 20

}
2.11.4 panic与recover 结合

在一个程序中只使用panic抛出异常会导致这个程序结束运行,但是与recover结合使用就不会—>recover必须要在defer语句里面才有用

只用panic

package main

import (
	"fmt"
)

func fn1() {
	fmt.Println("fn1")
}
func fn2() {
	panic("抛出异常")
}
func fn3() {
	fmt.Println("fn3")
}

func main() {
	fn1()
	fn2()
	fn3()
}
/*
运行结果
fn1
panic: 抛出异常                   
                                  
goroutine 1 [running]:            
main.fn2(...)                     
        E:/PRC/cs/main.go:11
*/

与recover结合

package main

import (
	"fmt"
)

func fn1() {
	fmt.Println("fn1")
}
func fn2() {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println(err)
		}
	}()
	panic("抛出异常")
}
func fn3() {
	fmt.Println("fn3")
}

func main() {
	fn1()
	fn2()
	fn3()
}

/*
程序输出:
	fn1
	抛出异常
	fn3

*/

他也可以接收其他异常,不一定要在你的程序中写panic

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值