云原生和devops越演越烈的今天,运维的要求越来越高了,为此特意决定开启go学习之路。此为学习笔记
第一天:go基础语法
一、申明变量
1、声明变量
var a int //整型,保存整数数值
var b string //字符串类型
var c []float32 //32位浮点型
var d func() bool //布尔型的函数变量
var e struct{ // 声明一个结构体类型的变量
x int // 拥有一个整型x字段
}
/* 除此之外还可以用一种懒汉型的变量申明方式
用var 和括号 将一组变量放在一起
*/
var (
a int
b string
c []float32
d func() bool
e struct{
x int
}
)
变量在声明时,go语言自动会对变量对应的内存区域进行初始化操作,每个变量会初始化成其类型的默认值
int float : 0
string : 空
bool : false
切片,函数,指针:nil
当然了,也可以在声明时赋值
2、声明变量的标准格式
var 变量名 类型 = 表达式
例如:
初始财产为100
var gold int = 100
3、短变量声明并初始化
var声明的精简写法
gold := 100
注意!!!:当使用 := ,推导声明写法左侧必须是没有定义过的变量。在多个短变量声明和赋值中,至少有一个新声明出现在左值中,编译器便不会报错。
4、多个变量同时赋值
变量交换
var a int = 100
var b int = 200
b,a = a,b
fmt.Println(a,b)
5、匿名变量
多重赋值时,如果不需要在左值中接受变量,可使用匿名变量_
例如:
func GetWeight() (float32,float32) {
return 90.51,86.72
}
a, _ := GetWeight()
_, b := GetWeight()
fmt.Println(a,b)
代码输出
90.51 86.72
二、数据类型
1、整型
按长度分为:int8、int16、int32、int64
无符号整型:uint8、uint16、uint32、uint64
其中uint8 为byte型,uint16 对应c语言的short型,unit64对应c语言中的long型
注意:在使用 int和uint时,要考虑在不同平台上的差异
2、浮点型
Go语言支持两种浮点型:float32和float64,遵循IEEE754标准
float32的浮点数的最大范围为3.4e38 可用定义为常量: math.Maxfloat32
float64的浮点数的最大范围为1.8e308 可用定义为常量:math.Maxfloat64
打印浮点数时,可以使用fmt包配合动词”%f”
代码如下
输出结果如下
3、bool型
Go语言中不允许强制转换为bool型
4、字符串
字符串在go语言中以原生数据类型出现,为双引号中的内容
例如:
单行字符串
str := “Hello World”
ch := “中文”
多行字符串
const str = line1
line2
line3
字符串中的每一个元素则称为字符,字符有以下两种:
1、unit8 也会是byte型,代表了ASCII码的一个字符
2、rune 也就是int32,代表一个UTF-8字符,常用于处理中文,日文等
可以通过fmt.Printf中的%T来输出类型
例如:
代码如下
输出结果为
字符串这里会涉及到转义符如下
三、指针
指针地址:每个变量在运行时都有一个地址,这个地址代表变量在内存中的位置。Go语言中使用&操作符放在变量前面对变量进行取地址操作。
例:
ptr := &v // v的类型为T
v表示被取地址的变量,被取地址的v使用ptr进行接收,ptr的类型为T,称作T的指针类型,代表指针
指针使用代码案例如下:
package main
import “fmt”
func main() {
var cat int = 1 //声明整型变量cat
var str string = “applt” //声明字符串变量str
fmt.Printf(“%p %p”, &cat, &str) //%p输出指针
}
执行结果为
0xc00006e090 0xc0000561e0 //0x为16进制前缀,输出结果每次均不会相同,代表变量运行时的地址
package main
import “fmt”
func main () {
//声明字符串
var flower = “腰花”
//对字符串取地址
ptr := &flower
//打印ptr指针类型
fmt.Printf("type: %T\n", ptr)
//打印ptr指针地址
fmt.Printf("address: %p\n", ptr)
//对指针取值
value := *ptr
//取值后的类型
fmt.Printf("type: %T\n", value)
//指针取值后就是指向变量的值
fmt.Printf("value: %s\n", value)
}
执行结果如下
type: *string
address: 0xc0000421f0
type: string
value: 腰花
取地址操作符&和取值操作符是一对互补的操作符,&取地址,根据地址取出地址指向的值
变量、指针地址、指针变量、取地址、取值的相互关系和特性
a、对变量进行取地址&操作,可以获取这个指针变量指向的原变量的值
b、指针变量的值是指针地址
c、对指针变量进行取值*操作,可以获得指针变量指向的原变量的值
使用指针进行数值交换来修改值
代码如下
package main
import “fmt”
//交换函数
func swap(a,b int) { //int,指针类型
//取a指针的值
t := *a
//取b指针的值
*a = *b
//将a指针的值赋给b指针指向的变量
*b = t
}
func main() {
//变量赋值3 4
x,y := 3,4
//交换变量
swap(&x, &y)
//输出变量
fmt.Println(x,y)
}
输出结果为
4 3
*操作符的根本意义就是操作指针指向的变量,当操作在右值时,就是取指向变量的值,当操作在左值时,就是将值设置给指向的变量。
四、栈
栈(stack):一种拥有特殊规则的线性表数据结构,只允许往代表线性表的一端放入数据,之后在这一端取出数据,按照后进先出的顺序(LIFO,LAST IN FIRST OUT)
往栈中放入数据叫做入栈,增加栈的元素数量,最后放入的元素总是位于栈的顶部,最先放入的数据总是位于栈的底部。不允许从栈底获取数据,也不允许对栈的成员进行任何查看和修改。
变量和栈的关系:栈可以用于内存分配,栈的分配和回收速度非常快。
下面代码可以用来展示栈在内存分配上的作用
package main
import (
“fmt”
)
func calc(a,b int) int {
var c int
c = a * b
var x int
x = c * 10
return x
}
func main() {
var y int = calc(3,4)
fmt.Printf(“%d”, y)
}
堆和栈相笔,堆适合不可预知大小的内存分配,但是速度较慢,并且会形成内存碎片
堆(heap)
二、变量逃逸(Escape Analysis)
go语言的编译器中有变量逃逸分析,由编译器分析代码的特征和代码生命周期,决定应该如何堆还是栈进行内存分配。
1、逃逸分析
package main
import “fmt”
//本函数测试入口参数和返回值情况
func dummy(b int) int {
//声明一个c赋值进入参数并返回
var c int
c = b
return c
}
//空函数,什么都不做
func void() {
}
func main() {
//声明a变量并打印
var a int
//调用void()函数
void()
//打印a变量的值和dummy()函数返回
fmt.Printfln(a, dummy(0))
}
执行命令行
go run –gcflags “-m -l” study3.go
D:\GO\golang\src\awesomeProject\studyday1>go run –gcflags “-m -l” study3.go
command-line-arguments
.\study3.go:28:13: main … argument does not escape //默认提示
.\study3.go:28:13: a escapes to heap //第28行a 逃逸到堆
.\study3.go:28:22: dummy(0) escapes to heap //dummy逃逸到堆
0 0
2、取地址发生逃逸
代码如下
package main
import “fmt”
//声明空结构体测试结构体逃逸情况
type Data struct {
}
func dummy() *Data {
//实体化c为Data类型
var c Data
//返回函数局部变量地址
return &c
}
func main() {
fmt.Println(dummy())
}
D:\GO\golang\src\awesomeProject\studyday1>go run –gcflags “-m -l” study3.go
command-line-arguments
.\study3.go:13:6: moved to heap: c //将c移动到堆中
.\study3.go:21:13: main … argument does not escape
.\study3.go:21:19: dummy() escapes to heap
&{}
堆和栈的原则:
变量是否被取地址
变量是否发生逃逸
- 本文作者: Devops旭
- 本文链接: http://yoursite.com/2020/03/15/go学习笔记day1/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!