go语言学习日记
Day1
变量声明
go语言提供多种变量声明方式,一般使用mod来声明和赋值变量:
- var a int 初值为0
- var a = 3 (自动识别)
- var a int = 3
- a := 3 [这个就是mod用法]
还有多行赋值
var( a int b string)支持多返回值
例如函数头应该长成这样
func test2()(int,int){ //匿名方式 return 123,456}
func test1(a int,b int)(re1 int, re2 int){ //具体变量 //函数体里面的内容 re1 = a+b re2 = a-b return //后面不用加东西}
func test1(a int,b int)(re1 int, re2 int){ //具体变量 //函数体里面的内容
return a+b,a-b //也可以这样}
func main(){ reA,reB := test1(1,2)}包的导入
在go里面导包是很经常的事情,很多东西都需要别的包里的函数来执行例如打印操作
import "fmt" //单行导入,需要双引号
import( //多行导入 fmt //不需要双引号 libA libB)
import( //别名导入 bag libA //此时libA的别名就是bag _ libB //此时为匿名导入,即触发导包时的init函数但是不使用包的内容 . libC //此时libC的命名空间就导入到全局环境下了)注意在导入包的时候,路径要求要从go的环境路径的相对路径开始,或者是之后用go mod
严格语法
在go语言里面,对于括号的位置是有严格要求的,对于函数体,if等一系列的需要{}的语句,其中的左括号必须跟在后面,不可以换行
func function1(){ //正确写法 //函数体}
func function2(){ //错误写法会报错 //函数体}
if 条件表达式 { //正确写法
}if 条件表达式{ //错误写法
}
if 条件表达式{
}else{ //两个括号必须写在同一行
}常量
在go中,常量用的是const关键字,用const关键字的时候和var一样,同样需要指定数据类型
const a intconst还能用来做枚举,使用方法如下
const( BEIJING = 0 SHANGHAI = 1 HANGZHOU = 2 //传统常量赋值枚举,注意此时是不用mod的)同样他可以像是数据库标识列一样自动展开
const( BEIJING = iota //此时的值从0开始计数 SHANGHAI //自动赋值为1 TIANJIN //自动赋值为2 ZHEJIANG //自动赋值为3)iota可以进行初值改变例如:
const( A = iota+65 //0+65 B //1+65 C //2+65 D //....)注意iota的改变值影响到下一个iota或者是结束之前,
const( A = iota+65 //0+65 B //1+65 C //2+65 D //3+65
E = iota + 0 // 4+0 F // 5+0)Day2
init函数
在go语言里,不同包在被导入的时候会调用特殊的函数(即init函数)
可以使用init函数进行一些初始化
例如这是libA源码
package libA
func init(){ //初始化函数体}这个是main.go的源码
package main
import "libA" //此时已经触发了libA的init(),前提是编译能过
func main(){ //函数体,但是需要调用libA的内容}指针
在go语言里面有着和c语言一样的指针调用机制,依旧基于以下运算符
- &取地址符
- *取值符
- var point int* 声明
代码如下
package main
func main(){ a := 12 var pa *int = &a}defer语句
在go语言中存在着其他的语言都没有的滞后触发的关键字,一般可以用于GC
defer语句修饰的函数都会在其他语句结束后,但是在当前的函数返回前被触发
例如
package main
import . "fmt"
func test1()(int){ println("1") return 2}
func main(){ defer println(test1()) println("3")}结果为132,因为defer的内容是打印test1的返回值所以2在最后,由于其实已经提前调用了,所以是1先出来
数组
go语言中有着和c语言一样的定长数组,定义如下
package main
func main(){ var myArray [10]int //创建了10个长度的数组,其中的默认值都为0}关于定长的数组传参的问题,对于大形参可以向下兼容小实参
循环语句
在go语言里面只有for循环,且使用方法是c语言的for或者是python的迭代器,示例如下
这个是c语言版本的
for i:=0;i<10;i++{ // //循环体}这个是迭代器版本
for i,v := range myArray{ //循环体,其中的i就是index,v就是值}当然其中的一些东西也可以匿名,像是这样
for _,v := range myArray{ //循环体,当角标没有意义的时候}切片(动态数组)
switch语句的fallthough还没记录
Day 3
slice切片
在go语言中,slice是比较常用的数组,有四种创建方式,并且用指针方式来验证是否为空
// 创建部分slice1 = make([]int,3) //创建三个长度的slice (第一种)
var slice1 []int = make([]int,3) //加了var和前置的类型(第二种)var slice1 []int //声明但是不初始化,此时的数组为空,slice1 == nil
func main(){ slice1 := []int{1,2,3} //使用mod和传统初始化(第三种) slice1 := make([]int,3) //创建三个长度的切片,默认值为0}// 访问slice1[0] = 999判断非空if slice1 != nil{ //判断体}概念:容量
在go语言中的容器是有容量和长度的概念的,len代表着当前的元素的个数,cap指的是不扩容最大长度为多少,如果元素被追加到超过cap,则会触发扩容机制

追加
对于slice可以追加元素,追加的元素会位于slice的最后
func main(){ slice1 := make([]int,3,5)//三个参数分别为类型,长度和容量,现在打印出来就是[0,0,0] len = 3 cap = 5 slice1 = append(slice1,1)//新建一个追加了1的元素的slice然后赋值给slice1,此时的值为[0,0,0,1] len = 4 cap = 5}扩容
当某一次追加导致其len > cap 此时就会触发扩容,扩容的原理是将原有的大小扩大cap,扩容后内存空间将
若现有一个cap = 5 的slice在触发扩容后,slice的cap将会变成10

这里的len应该在3那边,毕竟是抄的图