本期将go中的基础语法模块通过代码的方式写了一遍。
上传到了github.后续将不断通过更新项目总结go的学习以及总结。
下面的语法讲解转自golang官网,我简写了代码事例代码
golang官网: https://golang.google.cn/ref/...
golang开源社区: http://tour.studygolang.com/w...
代码地址: https://github.com/A1len/stud...
这一部分将对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的用法和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 同 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 语句会延迟函数的执行直到上层函数返回。延迟调用的参数会立刻生成,但是在上层函数返回前函数都不会被调用 可以理解为先进后出
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则执行到底 }
最后各位可以扫下方二维码关注我公众号,基本每周会推送一到两篇的go学习记录,后续学完基础语法,会准备写一个go微服务项目,源码依然放在github上面。