基本语法:包、函数、var变量、const常量、类型、流程控制、更多类型
包管理
go中没有public、private、protected等访问控制修饰符,它是通过字母大小表示能否被其他方访问或者调用的,大写的方法就表示是可以被调用的(相当于public),小写就只能在包内用。public与否的另一种说法是“是否导出”, 对应的,大写的表示是已导出的,小写开头的表示是未导出的,所以当你调用别的包里的方法就永远都是大写开始的fmt.PrintIn(math.pi)
另外,go的包名只需要写短的就行,它会根据放在哪个文件夹的路径下面去自动推导的
函数
func
关键字,add
函数名,(x, y int)
参数及其类型,当参数类型相同可以只用一个类型(类型声明是放后面的), 最后一个int
表示返回类型
func add(x, y int) int{
return x+y;
}
函数特点:
1,可以多值返回
func swap(x, y string)(string string)
{
return y,x
}
2,可以对返回值进行命名(但感觉可读性不是很好,代码多了容易看晕……
func split(sum int)(x, y int)
{
x = sum * 4 / 9
y = sum - x
return
}
变量
特点:
1,变量可以出现在包的级别,也可以出现在func中
2,可以一起初始化,可以不指定类型var java, c, test = 1, "dfer", true
package main
import "fmt"
var i, j int = 1,2 //可以在包内出现,可以指明类型
func main()
{
var c, python, java = true, false, "ok" //可以出现在函数内,可以不指明类型
fmt.Println(i, j, c, python, java)
}
3,简洁赋值语句 :=
可在类型明确的地方代替var声明,但不能出现在函数外
package main
import "fmt"
func main()
{
var i, j, int = 1, 2 //var的用法,要写变量,可能要声明,要赋值,太麻烦
k := 3 //就是上行赋值前的缩写
c, python, java := true, false, "ok" //多个赋值也可以
fmt.Println(i, j, k, c, python, java)
}
const 常量
类型
注意没有float
,一般就用float64
, int……
那一类我们一般就直接用int
, byte
相当于无符号八位整型uint8
, rune
用比较少相当于int32
表示一个unicode码点(?)
类型自动推导
就是在初始化一个变量的时候,直接给它一个值,系统就会自动根据这个值来判断类型
类型转换
在Go中,不同类型的项之间赋值时需要显示转换,不支持隐式转换
数值之间的转换比较简单:
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
或者更加简单的形式
i := 42
f := float64(i)
u := uint(f)
string和int…之间的转换稍微麻烦一点
int, err := strconv.Atoi(str) //string转换成int
string := strconv.Itoa(int) //int ->string
var data []byte = []byte(str) //str->byte
var str string = string(data[:]) //byte->string
//float<--> strinf
float, err:=strconv.ParseFloat()
string = strconv.Format()
Go的流程控制
1, 只有一种循环结构for 赋初值; 终止条件; 每次循环之后对变量的操作
不需要括号, 其中第一个和第三个条件是可以去掉的,可以连着分号去掉,这个时候跟while
语句没什么区别了
func mian()
{
//sum :=1
for sun := 1; sum <1000; sum +=1
{
sum+=sum
}
fmt.Println(sum)
}
for{}
就是一个死循环
2, if else 区别在于可以在执行判断前先执行一个语句if z:=x+y; z<a{}
其实我们要做的判断是z<a
但是在做这个判断前先做一个操作
3,switch:特点是Go只运行选定的case,而非之后所有的case,相当于在每个case后面自动提供了一个break
,除非以fallthrough
语句结束,否则分支会自动终止; 而且Go的另一重要点在于switch的case无需为常量,且不必取为整数
另外,也可以在执行前,先执行一个语句switch v:=x+y; v{}
在做判断之前可以做一个类似于初始化的操作
func main()
{
fmt.Print("Go runs on")
switch os:= runtime.GOOS; os
{
case "darwin" :
fmt.Println("Os X")
case "linux"
fmt.Println("Linux")
default:
//...
fmt.Println("%s. \n", os)
}
}
最后,可以用switch(无判断)+case 替代一堆if else
func main()
{
t := time.Now()
switch //没有判断
{
case t.Hour() <12
fmt. Println("Good morning")
case t.Hor()<17
fmt. Println("afternoon")
default:
fmt.Println("evening")
}
}
5, defer
1,defer语句会推迟到外层函数返回之后执行,但其参数会立即求值,只是返回前不会调用
2,defer的调用是被压入了栈中,会按先进后出的顺序调用
延时执行
func add1(x int) int
{
fmt.Println("add1")
return x+1
}
func main()
{
defer fmt.Println("world", add1(8))
fmt.Println("hello")
}
main函数运行到defer先不执行打印语句,但是会将参数add1先求出来但是不去调用,等全部执行完再去执行defer语句