简介
目前正在学Go,做下记录,温故而知新,初学coding的时候可以快速翻查用法,了解原理。
多重赋值
多重赋值时,变量的左值和右值按从左到右的顺序赋值
var a int = 100
b := 200
b,a = a,b // 实现交换
匿名变量
匿名变量 '_'表示,使用匿名变量时,只需要在变量声明的地方使用下划线替换即可。
a,_ = Get_data()
匿名变量不占用空间,不会分配内存。匿名变量与匿名变量之间不会因为多次声明而无法使用。
数据类型
整形(int8,int16,int32,int64)、浮点型、布尔型、字符串、数组、切片、结构体、函数(go语言的一种数据类型,可对函数类型的变量进行赋值和获取)、map、通道(channel)
数组
var variable_name [SIZE] variable_type
数组是一串固定长度的连续内存区域。
数组可以在声明时使用初始化列表进行元素设置:
var team = [3]string{"hammer","soldier","mum"}
根据元素个数确定数组大小
var team = [...]string{"hammer","soldier","mum"} // ...表示让编译器确定数组大小
遍历数组
for k,v := range team{
fmt.Println(k,v)
}
切片
https://www.cnblogs.com/followyou/p/12349883.html
map
https://www.cnblogs.com/followyou/p/12355313.html
函数
https://www.cnblogs.com/followyou/p/12348259.html
结构体
https://www.cnblogs.com/followyou/p/12358919.html
接口(interface)
https://www.cnblogs.com/followyou/p/12601846.html
指针
go拆分两个核心概念
- 类型指针 允许对这个指针类型的数据进行修改。传递数据使用指针,而无需拷贝数据。类型指针不能进行偏移和运算
- 切片 由指向起始元素的原始指针、元素数量和容量组成
go的指针类型变量拥有指针的高效访问,但又不会发生指针偏移,从而避免非法修改关键性数据问题。同时,垃圾回收也比较容易对不会发生偏移的指针进行检索和回收。
切片比原始指针具备更强大的特性,更为安全。切片发生越界时,运行时会报出宕机,并打出堆栈,而原始指针只会崩溃。
指针地址和指针类型
ptr := &v //v的类型为T &v取地址 &取地址操作符
//v代表被取地址的变量,被取地址的v使用ptr变量进行接收,ptr的类型为*T,称作T的指针类型。
// * 代表指针
变量、指针和地址关系:每个变量都拥有地址,指针的值就是地址
从指针获取指针指向的值
& 获取这个变量的指针
- 指针取值
&取出地址,*根据地址取出地址指向的值
变量、指针地址、指针变量、取地址、取值关系:
- 对变量进行取地址(&)操作,可以获得这个变量的指针变量
- 指针变量的值是指针地址
- 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值
*操作符根本意义就是操作指针指向的变量。当操作在右值时,就是取指向变量的值;当操作在左值时,就是将值设置给指向的变量
类型转换
T(表达式)
T代表要转换的类型。、
var a int32 = 1047483647
b:=int16(a)
堆栈知识
- 栈区(stack) --存储参数值、局部变量,维护函数调用关系等。
- 堆区(heap) --动态内存区域,随时申请和释放,程序自身要对内存泄漏负责
- 全局区(静态区) --存储全局和静态变量
- 字面量区 --常量字符串存储区
- 程序代码区 --存储二进制代码
int a=o; //全局变量
char *p1; //全局未初始化区
main() {
static int b=0; //全局初始化区
int c; //栈
char d[] = "abc:; //栈
char *p2; //栈
char *p3 = "hello"; //hello在常量区,p3在栈上
p1 = (char*)malloc(10);
p2 = (char*)malloc(20); //分配得来的10和20字节的区域就在堆区
strcpy(p1,"hello"); //hello放在常量区,编译器可能会将它与p3所指向的hello优化成一个地方
}
总体来讲,栈上的变量是局部的,随着局部空间的销毁而销毁,由系统负责。
堆上的变量可以提供全局访问,需要自行处理其声明周期。
关键字
defer
defer用于资源的释放,会在函数返回之前进行调用
var a,b := 1,2
c := func(a,b int) (c int){
c = a+b
defer func() {
c = c*2
}()
return
}
//6
流程判断
- 条件判断 if
- 条件循环 for
- 健值循环 for range
- 分支选择 switch
switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough
switch var1 {
case val1:
fallthrough
case val2:
...
default:
...
}
- 跳转 goto
- 跳出循环 break 和 继续循环 continue
健值循环(for range)
可以使用for range遍历数组、切片、字符串、map、及chnnel。
通过for range遍历返回值规律:
- 数组、切片和字符串返回索引和值;
- map返回健和值
- chnnel只返回通道内的值
遍历切片、数组
for key, value := range []int{1, 2, 3, 4} {
fmt.Printf("key%d, value %d
",key ,value)
}
遍历获得字符
str := "hello"
for key, value := range str {
fmt.Printf("key%d, value 0x%x
",key ,value) //%x 十六进制,小写字母,每字节两个字符
}
遍历map
m := map[string]int{
"a" : 1,
"b" : 2,
}
for key, value := range m {
fmt.Println(key,value)
}
遍历channel --从通道接收数据
c := make(chan int)
go func(){
//往通道内推送数据,然后结束并关闭通道
c <- 1
c <- 2
c <- 3
close(c)
}()
for value :=range c {
...
}
编译
export GOPATH=/home/golang/code
go build -o main /goinstall # 按包编译
go build -o mian main.go lib.go # 文件列表编译
go run
命令会编译源码,并且直接执行源码的main()函数,不会在当前目录留下可执行文件。
go run不会在运行目录下生成任何文件,可执行文件被放在临时文件中被执行,工作目录被设置为当前目录。
在go run的后部可以添加参数,这部分参数会作为代码可以接受的命令行输入提供给程序。
go run不能使用“go run + 包”的方式进行编译,如需快速编译运行包,需要使用如下步骤来代替:
- 使用go build生成可执行文件。
- 运行可执行文件。
go install
功能和go build类似,附加参数绝大多数都可以与go build通用。go install只是将编译的中间文件放在GOPATH的pkg目录下,以及固定地将编译结果放在GOPATH的bin目录下。
go install的编译过程有如下规律:
- go install是建立在GOPATH上的,无法在独立的目录里使用go install。
- GOPATH下的bin目录放置的是使用go install生成的可执行文件,可执行文件的名称来自于编译时的包名。
- go install输出目录始终为GOPATH下的bin目录,无法使用-o附加参数进行自定义。
- GOPATH下的pkg目录放置的是编译期间的中间文件。
测试
go test指定文件时默认执行文件内的所有测试用例。可以使用-run参数选择需要的测试用例单独执行
-v,可以让测试时显示详细的流程
-run跟随的测试用例的名称支持正则表达式,使用-run Test A$即可只执行Test A测试用例(假设TestA、TestAk、TestB、TestC会执行TestA、TestAk)。
go test -v -run testA main_test.go