本期将go中的基础语法模块通过代码的方式写了一遍。
上传到了github.后续将不断通过更新项目总结go的学习以及总结。
下面的语法讲解转自golang官网,我简写了代码事例代码
golang官网:https://golang.google.cn/ref/spec
golang开源社区:http://tour.studygolang.com/welcome/1
导读
- 基础语法
- 流程控制语句
基础语法
这一部分将对go中的包、函数、申明变量、基本数据类型、常量做一个描述
包
Go程序是通过将程序包关联在一起而组成。一个包又由一个或多个go源文件组成,这些源文件一起声明了属于该包的常量,类型,变量和函数,并且可以在同一包的所有文件中进行访问。这些元素可以 导出并在另一个包中使用。
import (
"fmt"
"math"
)
//1.通过import的方式导入包,可以像java一样多个imprt导入
//也可以通过上述方式
//2.在导入了一个包之后,就可以用其导出的名称来调用它。
//在 Go 中,首字母大写的名称是被导出的。
//Foo 和 FOO 都是被导出的名称。名称 foo 是不会被导出的。
//执行代码。然后将 math.pi 改名为 math.Pi 再试着执行一下
func main() {
fmt.Println(math.Pi)
}
函数
函数声明将标识符func绑定到函数。
package main
import ("fmt" "unsafe")
//函数可以返回一个或者多个值,具体看add和multipl函数
//两个或多个连续的函数命名参数是同一类型,可以只需要最后一个参数定义类型
//Go 的返回值可以被命名,并且像变量那样使用。
//返回值的名称应当具有一定的意义,可以作为文档使用
//没有参数的 return 语句返回结果的当前值。也就是`直接`返回
func add(x int, y int)(int){
return x+y
}
func multiple(x , y int)(string ,int){
return "hello",x
}
func multiple2(x , y int)(str string ,z int){
str="hello"
z=x
return
}
//外部实现,这里其实可以不定义结构体
//后续补充go:linkname
func FlushICache(begin,end int)
func main() {
x ,y :=multiple(42, 13)
fmt.Print(x,y)
}
申明变量和常量
申明变量可以通过var或者:= 常量使用const
package main
import "fmt"
//go当中声明一个变量可以通过var或者:=
//var可以作用在函数中也可以函数外
//:=只可以在函数中
//go有自动类型推断,如果有初始值,可以不带上变量类型
var initname="allen"
var name ,motherland string
var defaultvar string
//常量的定义和变量类似,只是换成了const来申明
const Pi = 3.14
func main() {
var num int
age:=18
fmt.Println(defaultvar,num,age)
}
基本数据类型
package main
import (
"math/cmplx"
"fmt"
)
/*
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
//一般需要用多大的可以选择多大的数字类型
//如果没有选择将会按照操作系统选择
//比如64位就会走int64
//go语言中的基础数据类型都有默认值,
//这很正常引用指针得指向一个内存空间,才算初始化了一个变量
//否则一个指针不初始化,很容易造成基础数据类型空指针。。。有点尴尬
byte // uint8 的别名
rune // int32 的别名,因为unicode是动态的所以选择32位可以完全满足,
新版本java对于这一块做了自动判断,节省空间
float32 float64
complex64 complex128
*/
var (
ToBe bool = false
MaxInt uint64 = 1<<64 - 1
z complex128 = cmplx.Sqrt(-5 + 12i)
)
func main() {
const f = "%T(%v)\n"
fmt.Printf(f, ToBe, ToBe)
fmt.Printf(f, MaxInt, MaxInt)
fmt.Printf(f, z, z)
}
流程控制语句
这部分没有全部列出来只是举了几个典型例子以及常用的说明,具体可以看官网
for
for的用法和java中基本一样,并且go里面是没有while了的
package main
import "fmt"
//for的使用和java中基本是一样的,只是少了一个()
//并且go当中没有while,使用for实现
//java中Doug Lea很喜欢这种写法
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
i := 1
for i < 1000 {
i += i
}
fmt.Println(i)
for {
break
}
}
switch
switch的变化比较多,没有条件的 switch 同 switchtrue一样。这一构造使得可以用更清晰的形式来编写长的 if-then-else 链 switch用法比java更方便灵活,不用显示的在语句中加break 如果要实现类似java的一个case成立继续执行后续的case可以使用fallthrough
package main
import (
"fmt"
"runtime"
"time"
)
//switch用法比java更方便灵活,不用显示的在语句中加break
//如果要实现类似java的一个case成立继续执行后续的case可以使用fallthrough
//case也可以直接使用判断语句
//以及type switch
//todo 后续看一下switch的实现源码
//感觉java的swtich语法糖和go比起来还是较弱,这也是java的历史原因
func main() {
fmt.Print("Go runs on ")
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
//fallthrough 打开注释看看结果
case "linux":
fmt.Println("Linux.")
//fallthrough
default:
// freebsd, openbsd,
// plan9, windows...
fmt.Printf("%s.", os)
}
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
var a interface{}
a = "abc"
switch t := a.(type) {
case string:
fmt.Printf("string %s\n", t)
case int:
fmt.Printf("int %d\n", t)
default:
fmt.Printf("unexpected type %T", t)
}
}
defer
defer 语句会延迟函数的执行直到上层函数返回。延迟调用的参数会立刻生成,但是在上层函数返回前函数都不会被调用 可以理解为先进后出
package main
import (
"fmt"
)
//defer的操作其实是一个压栈的方式调用
//先进后出FILO
//可以一次执行下面的三个例子
//另外通过例子3其实可以知道defer是有数据拷贝的
//换句话说执行defer的时候数据就保存了一个份
//后续变量怎么改变defer还是输出同样的信息
//TODO defer的使用场景后续补充,暂时先当try catch finally使用
func main() {
fmt.Println("counting")
a:="hello world"
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
//1.os.Exit(0)//直接推出不会执行defer
//2.return//遇到return才返回
defer fmt.Println(a)
//3.a="hello defer"
fmt.Println("done")//没有return则执行到底
}