第一个程序
package main //声明整个文件所在的包
import "fmt"//引入程序中要用的的包 ,为了使用包下的函数,比如Println
func main() {//主函数 程序的入口
fmt.Println("hello world")//在控制台打印
}
特殊的: func main() {中的{一定要并行否则运行错误 ,因为golang要求的是精简
fmt可以看作是c语言中的stdio这样的库,以提供使用的函数
变量
变量的声明
例如现在需要一个年龄作为变量即age
那么我的定义即为var age int
同一个变量名,不能重复定义
变量的赋值
我需要对我定义的age进行赋值
则为age=18
也可以在定义时进行赋值即为
var age2 int = 19
变量的使用
可以使用包fmt下的函数Println进行打印
fmt.Println("age=", age)
特殊的 与c语言不同的是系统不会自动转换不匹配的类型
变量的四种使用方式
1.第一种使用Println
rt
2.第二种只定义不赋值,使用默认值
3.不定义类型,由赋值的数推断变量的类型
即
var num3 = 10
4.不使用var关键字,后面的赋值使用:=(最为简略)
即
sex := "男"
支持同时定义多个变量
全局变量
var ( n9 = 500 n10=9.8 )
以上定义在函数外
在函数内部定义的是局部变量
数据类型
基本数据类型
数值型(整数类型,浮点数类型)
整数类型
类型 | 占用储存空间 | 表示范围 |
int8 | 1 | -128-127 |
int16 | 2 | -32768-32767 |
int32 | 4 | -2147483648-2147483647 |
int64 | 8 | -2^63~2^63-1 |
大小不能够溢出
无符号整型:在相应的类型前面加上u
如果只有int或者是uint 那么就根据电脑的操作位数决定int的储存空间
我的系统为64位,则goland中的int类型为8个字节
但是为了真用更小的空间则使用更小的几种表达方式
字符型
类型 | 储存空间 | 表数范围 |
float32 | 4 | -3.403E38~3.403E38 |
float64 | 8 | -1.798E308~1.798E308 |
64位的比32位更加精确
默认的类型为float64
布尔型
字符串
复杂数据类型
指针
数组
结构体
管道
函数
切片
接口
map
运算符
算数运算符
+ | - | * | / | % | ++ | -- |
++与--同理于c语言的自增 自减操作
赋值运算符
= | += | -= | *= | /= | %= |
关系运算符
== | != | > | < | >= | <= |
逻辑运算符
&& | || | ! |
位运算符
& | | | ^ |
其它运算符
& | * |
&:取地址运算符
*:取指针变量对应的数值的运算符
分支结构
必须按照以下要求编码
单分支结构
if 条件表达式{
逻辑代码
}
条件可以通过分号分隔开
双分支结构
if条件表达式{
逻辑代码1
} else {
逻辑代码2
}
多分支结构
使用else if,使用方法同理于c语言
switch语句
使用方法(1)
1.case后的值必须于switch后的一样 (即使是int32于int64的区别也不行)
2.switch语句后是一个表达式,这个表达式的结果一次和case进行比较,满足结果的就执行冒号后面的代码
3.兜底分支(都不满足,可以放在任意位置)
default:
。。。。。
4.case后可以有多个值,如果多个值并列,那么采用共同的结果语句
5.与c语言不同的是不需要写break
6.switch也可以类似于if使用
7.switch后可以直接声明一个变量,分号结束
8.switch穿透,利用fallthrough关键字,如果在case语句后增加fallthrough,则会继续执行下一个擦色,也叫switch穿透
由图可见,如果不加fallthrough,那么只会输出一个C,加上之后将作用效果穿透到了下一个,所以也输出了D
循环结构
只有一种for循环
(与c语言类似)
函数
简单的函数的定义和引用
func name (形参列表)(返回值类型列表){
执行语句
return +返回值列表
}
package main
import "fmt"
func cal(num1 int, num2 int) int { //返回值类型相同,使用一个就行
var sum int = 0
sum += num1
sum = +num2
return sum
}
func main() {
sum := cal(10, 20)
fmt.Println(sum)
}
1.尽量采用多个英文单词首字母大写拼合的命名规则
2. 形参列表
个数:可以是一个参数,可以是n个参数,可以是0的参数
作用:传入值,接受外来参数
3.返回值类型列表
返回值的类型写入
1.如果无返回值
参考c语言的void类型函数
2.如果有一个返回值
3.如果或有两个返回值
需要注意的是
定义的时候需采用这种方式
但是如果我们只需要一个sum的值的话
采用一个下划线来代替第二个返回值,意为忽略第二个值(更为详细的值是在Go语言中,下划线(_
)通常用作空白标识符(blank identifier)。空白标识符在语法上是有效的标识符,但它并不引用任何变量。在很多情况下,它被用于忽略某个值或避免编译器错误,但不使用实际的变量。)
4.例题:实现两数的交换
标错误的示例
形参的变化 不会影响到实参,类似于c语言
正确的实例
5.golang中的函数不支持重载(简单的说就是不能重名)
在程序设计中,重载(Overloading)是指在同一个作用域内,使用相同的函数名或操作符,但其参数列表或操作数的类型和个数不同,从而让同一个名称的函数或操作符具有多个不同的实现方式。
重载的主要目的是提高代码的灵活性和可读性。通过重载,可以使用相同的函数名或操作符来执行不同的操作,而无需为每个不同的操作定义一个新的名称。这使得代码更加简洁、易读,并且方便了开发者的使用。
在函数重载中,函数名相同但参数列表不同,可以是参数类型不同、参数个数不同,或者两者都不同。编译器根据调用时提供的参数来决定调用哪个版本的函数。
6.golang中支持可变参数
就是可以存入不确定数量的参数
func test(args ...int) int
可以传入任意数量的
可以把这些看作为一个数组用于处理
7.基本数据类型和数组默认都是值传递的,即进行值拷贝,在函数内修改,不会影响到原来的值
如果参数类型为指针,则能改变值,传入的时候也需要传入一个地址。与c语言类似
8.go语言中函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用(函数类型)
则a(10)等价于test(10)
9.支持对函数返回值命名
传统要求:返回值和返回值类型对应,顺序不能差
升级写法
包
1.package进行包的声明,建议:包的声明与这个包所在的文件夹同名
2.main包是程序的入口包,一般main函数会放在这个包下
3.打包语法
package 包名
4.引入包的语法
import “包的路径”
包名是从$GOPATH/src开始的
5.多个包一次性导入
import(
“fmt”
“。。。”
)
6.在函数调用的时候要定位到其所在的包
7.函数首字母大写,函数才能被其他函数访问
8.一个目录下不能有重复的包
9.包名和文件夹名可以不一样
10.一个目录下的同级文件属于一个包
11.包是什么
(1)在程序方面,所有使用相同package包名的源文件组成的代码模块
(2)在文件层面就是一个文件夹
错误处理机制
1.错误类型: 在Go中,错误是一种内置的接口类型,称为error
。该接口定义如下:
type error interface { Error() string }
任何实现了Error()
方法的类型都可以被视为一个错误。通常,函数会返回一个值和一个错误。如果错误为nil
,表示操作成功,否则表示操作失败,错误值描述了失败的原因。
2.返回值检查: 函数经常返回一个值和一个错误。调用者在使用函数的返回值之前通常会检查错误是否为nil
。
result, err := someFunction() if err != nil { // 处理错误 } // 使用 result
3.
自定义错误: 开发者可以通过实现Error()
方法来创建自定义错误类型。这使得错误信息更加详细且易于理解。
type MyError struct { message string } func (e *MyError) Error() string { return e.message }
4.
panic和recover: Go中有两个用于处理异常的内置函数,即panic
和recover
。然而,它们不是用于一般的错误处理,而是用于处理严重错误的情况,例如程序中止。一般情况下,不鼓励使用这些函数进行错误处理。
-
panic
: 用于引发运行时恐慌,导致程序崩溃。 -
recover
: 用于从panic
中恢复,但一般情况下不应该在正常的错误处理中使用。
5.defer语句: Go中的defer
语句用于在函数退出时执行某个语句。通常,它用于在发生错误时进行清理工作。
func example() (result int, err error) { // 在函数退出时关闭文件 defer func() { if file != nil { file.Close() } }() // 执行一些操作,可能会返回错误 // ... return result, err }
数组
数组的定义:
var 数组名 [数组大小]数组类型
金盘录入的方法
数组的遍历
方法一:普通for循环
for i := 0; i < len(scores); i++ {
fmt.Printf("第%d个人的成绩是%d\n", i, scores[i])
}
方法二:键值循环
//模板
for key,val:=range coll{
...
}
coll是要遍历的内容,key和val是两个值(照搬即可)
key是每次遍历得到的索引,val是索引位置上的值
for key, val := range scores {
fmt.Printf("%d %d", key+1, val)
}
二维数组
二维数组的遍历
方法一
方法二
切片(slice)
切片定义在数组之上
定义的切片长度[ ]不写,int类型,arr是原数组
[1:3]切片,切除的一段片段,索引从一开始,到三结束(不包含3)
切片的容量是切片长度的2倍左右
切片的部分所储存的地址就是数组的地址,切片上值的改变也会影响到数组
切片的创建
方法一:截取一个数组,如上述
方法二:通过make内置函数来创建切片,基本语法:var切片名[type = make([],len,[cap])(三个参数)(类型,长度,容量)
方法三:定义一个切片,直接就指定具体数组,类似于make
slice1:=[]int{1,4,7}
切片的遍历
与数组相同
tips
切片的简写
(1)var slice = arr[0:end]
(2)var slice = arr[start:10]
(3)var slice = arr[start:end]=arr[:]
切片也可以继续切片
切片可以动态增长
使用append在结尾追加内容
也可以使用append把切片追加给切片
切片的拷贝
copy(a,b)把b复制给a
映射(map)
(1)映射:go语言中内置的一种类型,它将键值相关联,我们可以通过键key来获取想应的值value。
比如
键值对 | 对匹配的信息 |
学生学号 | 学生名字 |
1111 | 2222 |
前为key 后为value
(2)基本语法
var map变量名 map[keytype]valuetype
只声明不赋值,内存空间中不分配内存,使用make函数即可分配
此处key和value是无序的
key是不可以重复的,如果重复后一个会替换前一个
map的三种创建方式
方法一:
var a map[int]string
a = make(map[int]string, 10)
方法二:
b:=make(map[int]string, 10)
方法三:
c := map[int]string{
2001: "zhangsan",
2002: "lisi",
}
map的操作
1.增加和更新操作
func main() {
//定义
b := make(map[int]string, 10)
//增加
b[20050924] = "arthur"
b[20050925] = "ab"
//修改
b[20050924] = "art"
fmt.Println(b)
}
2.删除操作
delete(map,“key”),如果key存在就删除key-value,如果k的y不存在,不操作
func main() {
//定义
b := make(map[int]string, 10)
//增加
b[20050924] = "arthur"
b[20050925] = "ab"
b[20050926] = "art"
//删除
delete(b, 20050926)
fmt.Println(b)
}
3.清空操作
(1)遍历key,逐个删除
(2)map=make(。。。),make一个新的,让原来成为垃圾
4.查找操作
value,bool:=map[key]
value为返回的value,bool为是否返回,ture或false
//定义
b := make(map[int]string, 10)
//增加
b[20050924] = "arthur"
b[20050925] = "ab"
b[20050926] = "art"
//查找
value, flag := b[20050924]
fmt.Println(value, flag)
5.获取长度
len函数
//定义
b := make(map[int]string, 10)
//增加
b[20050924] = "arthur"
b[20050925] = "ab"
b[20050926] = "art"
//获取长度
fmt.Println(len(b))
6.遍历:for-range
func main() {
//定义
b := make(map[int]string, 10)
//增加
b[20050924] = "arthur"
b[20050925] = "ab"
b[20050926] = "art"
//遍历
for k, v := range b {
fmt.Printf("key为:%v value为%v", k, v)
}
}
//遍历
a := make(map[string]map[int]string)
a["班级1"] = make(map[int]string, 3)
a["班级1"][2001] = "zhangsan"
a["班级1"][2002] = "aclnia"
a["班级1"][2003] = "sbgvkljh"
a["班级2"] = make(map[int]string, 3)
a["班级2"][2001] = "zhaehgn"
a["班级2"][2002] = "acdgmhia"
a["班级2"][2003] = "s3egjh"
for k1, v1 := range a {
fmt.Println(k1)
for k2, v2 := range v1 {
fmt.Println(k2, v2)
}
}