目录
go作为学习的第n门编程语言,学习笔记将主要聚焦于go与其他语言的区别。写业务代码主要还是主要还是靠代码逻辑,与语言关系不大。
变量篇
go变量的声明:
1)声明方式1
var i int
var n1, n2 ,n3 int
var n1, s2 ,n3 int
在变量名后面追加定义变量类型,如果声明的时候不赋值,将有一个默认值,int和float的默认值为0,string的默认值为"",bool的默认值为false。
2)声明方式2
var num = 10.0
name := "123"
var n1, s2 ,n3 = 100, "abc", 666
n1, s2 ,n3 := 100, "abc", 666
var (
n3 = 300
n4 = 900
name = "abc"
)
不显式的指定变量类型。将根据所赋值的参数的类型自动推导。可以用var关键字或者使用:=运算符来表达要声明变量。
go变量使用的注意事项:
1)整型在赋值的时候不会自动截断
会报错,如以下代码。第3,4行均会报错
var num int = 0
var f float32 = 10.11
num = f //error line
num = 123.33 //error line
// error info :
// cannot use 123.33 (untyped float constant) as int value in assignment
即使是int8给int16赋值也不行。需要使用类型转换,才可以正常赋值。这里的类型转换的使用方法与python类似。具体如下:
var ori int8 = 100
var v1 int16 = int16(ori)
var v2 folat32 = float32(ori)
fmt.printf("%d,%f"v1,v2) // 100,100.0
2) 在go中的基本数据类型
go中的基本数据类型有:int, float(不显式指定变量类型时,小数默认是float64位), bool, string, complex, byte(可以看作int8的别名), rune(可以看作int32的别名,也是一个unicode,通常被用于存储一个中文字符)。
值得注意的是,go中没有char类型。string中每一个字符,是用uint8来存储的。float32和float64除了占用空间不同以及值的取值范围不同,float64的精度比32要高,当计算时追求高精度,可以使用float64。
var s string = "213"
fmt.Printf("%T,%s", s[0], s) // uint8,213
var r rune = 666
fmt.Printf("%T,%d", r, r) //int32,666
3)go中的string
在go中,string的值是不能改变的。可以把go中的string理解成c中的const char *来用,无法通过索引来修改string的值。
在go中给sting赋值的时候,遇到特殊符号如' " \,可以像C++,采用转义字符,在go中还支持使用``,包含在``中的字符,无论是什么,都将原生输出。
go中,其他基本数据类型转string一般使用fmt.Sprintf,如str = fmt.Sprintf("%d",num)。也可使用strconv包中的func FormatInt(i int64, base int) string函数。string转其他数据类型可以使用strconv包中的strconv.ParseBool(str)等函数。
4)变量的值类型和引用类型
值类型:包含基本数据类型,int,float,bool,string,数组,结构体等
引用类型:包含指针,slice切片,管道,map,interface等
值类型在内存中,是直接存放变量的值的。通常被分配在栈中。
引用类型存储的是一个地址,通常为指向一个堆空间的地址,当没有指针指向的时候,会被认定为垃圾,自动回收。
5)变量的首字母
在go中,变量的首字母的大小写将影响这个变量的访问权限。当首字母大写的时候,这个变量是可以被其他包访问的,类似于在C++加了关键字public,首字母小写则为私有的,即private。
运算符篇
go中运算符的注意事项
在go中基本的运算符与C++基本相同。如&&,||,!,=,+=,<<,<=等
go中的++,--运算符只能单独使用。并且没有前++,具体用法如下。
var i int = 0
i++ // correct
a := i++ // error line
++i // error line
程序流程控制基本语法篇
if
go使用if时,判断的表达式可以不用()括起来,执行的函数体必须加大括号,即使只有一条语句。if允许在判断条件时声明变量,else不能单独一行来写,不然会报错。如下都可以
if age:=20; age > 18{
fmt.Println("666")
}
if age > 18{
fmt.Println("666")
}else{
fmt.Println("123")
}
switch
go中switch不需要加break,一个case可以有多个表达式。
switch i{
case 1,2:
fmt.Println("case1,2")
case 3:
fmt.Println("case3")
case getNum(arg):
fmt.Println("func")
default:
fmt.Printlb("def")
}
另外,go还支持switch后不带表达式的用法,类似于if-else
switch{
case i == 1:
fmt.Println("case1,2")
case i == 3:
fmt.Println("case3")
case i == getNum(arg):
fmt.Println("func")
default:
fmt.Printlb("def")
}
switch可以用fallthrough穿透一层,不需要判断下一个case的条件,直接执行下个case的函数体。(感觉没什么用)
go可以使用switch来判断变量类型。
for
与C++的for基本一样,除了不需要带小括号。for{ 等价于 for ; ; {
go也支持for-range的方法快速遍历可遍历对象。语法如下
for index, val := range str {
fmt.Println(index, val)
}
while
在go中没有while和do...while
break,continue
在go中break和continue可以带一个参数。可以通过标签指定要跳到哪一层去。其他与C++一样。
函数篇
go中函数的特点
在go中,函数最大的特点就是可以有多个返回值。函数名首字母的大小写也决定了这个函数能不能被其他包使用。go默认是值拷贝传递,如需改变值,需传指针或者引用传递。
对于不需要用到的多余的返回值可以使用_占位
go中定义函数的语法:
func funcName(arg1 int, arg2 string)(bool, float32){
....
return returnArg1, returnArg2
}
go不支持函数重载
在go中,函数也是一种数据类型,函数名类似c中的函数指针。可以将函数名赋值给一个变量,然后可以通过变量调用函数。
func getSum(args ...int) int {
var res int
for _, v := range args {
res += v
}
return res
}
func main(){
a := getSum
fmt.Printf("a的类型为%T,getSum的类型为%T",a,getSum)
//a的类型为func(int, int) int,getSum的类型为func(int, int) int
res := a(1,2)
fmt.Printf("%d",res) //3
}
init函数
每一个源文件都可以有一个init函数,在main函数执行前,会被调用。
匿名函数
可以声明的同时直接调用,也可以将函数地址赋值给一个变量名。
defer关键词
go执行到一个defer的时候,不会立即执行,而是将语句压入栈中,函数执行完毕后,在一次出栈执行。压栈的时候,涉及的参数默认都是值拷贝。一般用于database和file的close()。