在上一篇文章中讲述了配置与输出,接下来我们进入下一步的学习
前言:Go语言特性
Go语言是Google公司开发的一种静态的,编译型并自带垃圾回收和并发的变成语言.
Go语言的风格类似C语言,其语法在C语言的基础上进行了大幅度的优化,去掉了不需要的表达式括号,循环也只有for一种表示方法,就可以实现数值,键值等各种遍历.因此, Go语言上手非常容易.
Go语言最具有特色的特性莫过于goroutine. Go语言在语言层可以通过goroutine对函数实现并发并行. goroutine类似于线程,但并非线程, goroutine会在Go语言运行时进行自动调度.因此,Go语言非常适合用于高并发网络服务的编写.
一、Go的基本语法以及使用
1、整型类型
Go对类型的长度有极大要求
长度类型:int8 int16 int32 int64
对应无符号类型:uint8 uint16 uint32 uint64
2、浮点型
Go语言支持两种浮点整数:
float32:最大范围约为 3.4e38,可以使用常量定义:math.MaxFloat32
float64:最大范围约为 1.8e308,可以使用常量定义:math.MaxFloat64
3、布尔型
布尔型数据只有true和false
Go语言中不允许将整型强制转换为布尔型,代码如下:
fmt.Println(int(n) * 2)
编译错误,输出如下:
cannot convert n (type bool) to type int
布尔型无法参与数值运算,也无法与其他类型进行转换
4、字符串型
对于字符串类型,以双引号为扩住的则为字符串类型,可放入非ASCII码的字符
str := "hello world"
ch := "中文"
5、切片
接下来讲述Go语言中的切片(能够动态的的分配空间)是一个拥有相同类型元素的可变长度序列
var arr[]类型 // 初始化的时候定义,后面追加上类型 如int string float等
例:var arr[]int
切片的元素使用”[]“来进行访问,在[]里提供数值索引可获取相对应的value值,切片的索引默认访问是从0开始,如赋值时没有从对应数字开始则默认值会自定义为0,以下贴上代码
// 创建切片
item := make([]int, 3) //创建一个容量为3的整型切片 ps:其实就是创建一个容量只能为3的切片,但是value都只能为int
item[0] = 0 //为切片元素赋值
item[1] = 1
item[2] = 2
fmt.Println(item)
输出:[0 1 2]
如不按顺序来进行赋值
// 创建切片
item := make([]int, 10) //创建一个容量为10的整型切片 ps:其实就是创建一个容量只能为10的切片,但是value都只能为int
item[7] = 77
item[8] = 88
fmt.Println(item)
输出:[0 0 0 0 0 0 0 77 88 0] // 未定义的索引值则默认为0
我们也可以进行切片追加(append)
info := append(item, 99)
fmt.Println(item, info)
输出: [0 0 0 0 0 0 0 77 88 0 99] // 在原来的基础上追加了99
替换覆盖(copy)
test := []int{1,2,3,4,5}
copy(info, test)
fmt.Println(info)
输出:[1 2 3 4 5 0 0 77 88 0 99]
字符串也可以按照切片的方式进行操作(字符串截取功能,从第1位开始数)
str := "hello world"
fmt.Println(str[6:])// 输出截取,这里注意的是截取只能截取字符串类型的,其他类型截不了
输出:world
以上是简单的一些小案例,还有更多的一些语法技巧函数,可上Go官方文档查看http://docscn.studygolang.com/doc/
二、变量
1、变量声明
var a int//声明一个整型类型的变量,可以保存整数数值
var b string//声明一个字符串类型的变量
var c []float32//声明一个32位浮点切片类型的变量,浮点切片表示由多个浮点类型组成的数据结构
var d func() bool//声明一个返回值为布尔类型的函数变量,这种形式一般用于回调函数,即将函数以变量的形式保存下来,在需要的时候重新调用这个函数
var e struct{//声明一个结构体变量,拥有一个整型的x字段
x int
}
标准定义:var 参数名 类型
批量声明
var (
a int
b string
c []float32
d func() bool
e struct{
x int
}
)
初始化变量(标准格式)
var 变量名 类型 = 表达式
例:小明考试考了100分
var score int = 100
初始化变量(短变量声明)
score := 100
// 如果score已经被var初始化过,则这个时候会报错,例如以下
var score int = 90
score := 80
// error : no new variables on left side of :=
// 报错提示的原因是左边没有新的变量名出现,则不允许重新赋值
// ps:也可以支持多个变量一直赋值
info, score, x = 0, 1, 2
2、匿名变量(没有名字并且不需要用到的变量,可减少内存空间)
在开发过程中,有时候调用某个方法后,发现一些参数是不需要的,但是又不想浪费内存去接收到,那么可以用”_“下划线进行代替
func item() (int,int) {
return 100, 200
}
a, _ := item()
fmt.Println(a)
输出:100
// 当然,我们也可以在赋值的时候这么做
_, score := 0, 80
fmt.Println(score)
输出:80
Go在内存这方面还是很强大的,完全不用担心内存溢出,可以大胆放心使用
三、函数
函数的常规定义
func 方法名(参数列表) 返回值 {
定义
}
例:
func item(a) int {
return 100
}
1、函数的值(闭包)
函数值不仅仅是一串代码,还记录了状态。Go使用闭包(closures)技术实现函数值,Go程序员也把函数值叫做闭包。我们看个闭包的例子:
func f1(limit int) (func(v int) bool) {
//编译器发现limit逃逸了,自动在堆上分配
return func (v int) bool { return v > limit}
}
func main(){
closure := f1(3)
fmt.Printf("%v\n", closure(1)) //false
fmt.Printf("%v\n", closure(3)) //false
fmt.Printf("%v\n", closure(10)) //true
}
ps:程序执行流程
1、程序进入main后,发现调用了f1方法并带入了”3“,此时返回一个闭包
2、走到下面closure(1)时,程序发现有传入闭包值”1“
3、程序走进上面的方法内,此时limit = 3, 闭包内的v = 1
4、走到下面的逻辑判断中,引用闭包内的v,并且将v与limit做比较
5、最终得到结果,返回给下面的 fmt.Printf("%v\n", closure(1))进行输出
6、依次类推
函数可变参数
可变参数,即参数不是固定死的一个值,可以有无限N个,例如fmt.Printf函数那样, 但只有最后一个参数可设置为可变参数
声明
func 函数名(变量名...类型) 返回值
举例:
func getData(str string, vals... int) (num int) {
for _,v := range vals {
num += v
}
num += len(str)
return
}
func main(){
fmt.Printf("%d\n", getData("abc", 1,2,3,4,5 ))
}
输出:18
将传入的1,2,3,4,5 循环追加给num值,最后再加上str的长度 15 + 3 = 18
注意:在for后面一点要加上匿名函数,否则始终不会循环追加最后一个值,如去掉加起来则为13
getData第二个参数即最后一个参数则为可变参数
2、函数的延迟执行 defer
包含defer语句的函数执行完毕后(例如return、panic),释放堆栈前会调用被声明defer的语句,常用于释放资源、记录函数执行耗时等,有一下几个特点:
- 当defer被声明时,其参数就会被实时解析
- 执行顺序和声明顺序相反
- defer可以读取有名返回值
//演示defer的函数可以访问返回值
func f2() (v int) {
defer func (){ v++}()
return 1 //执行这个时,把v置为1
}
//演示defer声明即解释
func f3(i int) (v int) {
defer func(j int) {
v+= j
} (i) //此时函数i已被解析为10,后面修改i的值无影响
v = 9 // v = 9
i = i*2 // i = 20
return
}
//演示defer的执行顺序,与声明顺序相反
func f4() {
defer func() {fmt.Printf("first\n")} ()
defer func() {fmt.Printf("second\n")} ()
}
func main(){
fmt.Printf("%d\n", f2()) // 13
fmt.Printf("%d\n", f3(10)) // 19
f4() //second\nfirst\n
最终输出:
2
19
second
first
执行过程:
1、首先调用了f2,由于defer是在return执行后再去执行的,所以当return 1时,附加v++ 所以最终返回值为2
2、调用了f3并传入值为10,进入到f3方法中,v = 9,i = 20,走到defer,此时i已经被解析成了10,所以后面的相乘无影响
3、接着进入defer后,设定了j值,此时j = i = 10,v是后面新赋的值,也没有被解析,所以v+=j 则等于 v = 9+10 = 19,最后返回19
4、最后一步f4是返回的顺序是相反的,则验明了defer是在声明的倒序执行的
ps:一般典型的用来计算耗时,资源关闭等,相关操作可按照业务逻辑编写
Golang学习文章会持续更新,谢谢