GO 语言基础
距离第一次学习 GO 已经很久了,这次重新开始,我希望能够将整个过程记录下来。首先便是对于 GO 基础语法的学习。
文件结构
GO 语言是一种非常严格的语言,其中一个表现,就是它严格规定了 GO 源代码、可执行程序以及相关库在系统中的放置位置。比如对于笔者所用的 Mac 系统,GO 的根目录默认为~/go
,该根目录可以通过配置或者指令进行修改。GO 源代码、可执行程序以及相关库都要放置在根目录下,其中
-
GOPATH/src
用来放源代码,每个工程用单独的文件夹存放,文件夹可以嵌套 -
GOPATH/pkg
用来放库文件,包括从网上引入的库和本地生成的库 -
GOPATH/bin
用来放生成的可执行程序
由于严格制定了路径,在任意路径下,都可以对制定 GO 程序进行操作。
例如存放在目录GOPATH/src/some_path/some_lib
下的库工程,可以通过go install some_path/some_lib
来构建,并将构建的结果安装到GOPATH/pkg/ARCH/some_path/some_lib.a
,如果有其他工程需要使用该库文件中定义的函数,可以通过语句import "some_path/some_lib"
来导入。
而对于存放在目录GOPATH/src/some_path/some_app
下的应用程序工程,可以通过go install some_path/some_app
来构建,并安装到GOPATH/bin
目录下,如果已经将GOPATH/bin
目录加入到系统的PATH
路径下,则可以直接在终端通过some_app
命令调用该应用程序。
基本元素
包 package
GO 语言像 Java 一样存在包的概念,每一个 go 文件都要在开头指定它从属的包,即每一个 go 文件的开头第一句必须是:
package name
对于可执行程序,包名必须是main
,对于库工程,包名最好为所属的文件夹名。
引入库
GO 语言中引入其他库的方式如下
import "lib_name"
如果需要引入多个库,则
import (
"lib1_name"
"lib2_name"
"lib3_name"
)
变量
定义一个变量的语法为
var <var_name> <var_type> [= <default_value>]
事实上,对于给定初始值的变量,其类型已经被初始值隐含,不需要再行定义,所以对于有初始值的变量也可以如此定义
<var_name> := <default_value>
变量也可以一次定义多个,如
var x int, y float32
var a, b float64 = 1.414, 3.14
str, flag := "Hello World", true
常量
对应常量而言,初始值是必须的,因此不再需要显式的指定类型,其语法如下
const <const_name> = <default_value>
多个常量也可以一次定义,语法如下
const (
<const1_name> = <default_value1>
<const2_name> = <default_value2>
)
基本类型
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // alias for uint8
rune // alias for int32
// represents a Unicode code point
float32 float64
complex64 complex128
函数
GO 语言的函数定义语法为
func <func_name>([<para_name> <para_type> [, other parameters] ]) [return_type] {
//function body
[return <return_value>]
}
返回值可以对于一个,例如
func swapString(str1,str2 string) (string,string) {
return str2,str1
}
程序流控制
循环
GO 语言只有一种循环体,那就是 for 循环体,基本语法为
for [init_statement];<condition>;[post_statement] {
//looping body
}
例如打印从1-100数字的实现如下
for i:=0;i<100;i++ {
fmt.Println(i+1)
}
如果只有条件,没有初始语句和后处理语句,则for
循环后面的两个分号可以删除,这时,for
循环相当于其他语言中的while
循环,例如(2^100):
sum := 1
for sum<100 {
sum += sum
}
若连条件也没有,则相当于while(true)
无限循环:
func main() {
//initial statements
for {
//looping statements
if <condition> {
break;
}
}
}
条件
if [<short statement>;]<condition> {
//if body
}[ else if <condition2> {
//else if body
}] [else {
//else body
}]
Switch
switch
其实是一种特殊形式的if else
结构,需要注意的是 GO 语言中每个 case
之后都隐含break
,不再需要显式的写break
,例如
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Print("Go runs on ")
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
case "linux":
fmt.Println("Linux.")
default:
// freebsd, openbsd,
// plan9, windows...
fmt.Printf("%s.", os)
}
}
defer:结束时运行
defer
用于指定函数结束时需要运行的语句,这对于打开资源,必须在退出时释放的情况非常有用。注意,每个defer
都只能执行一句命令,但可以通过定义一个临时的函数将多个语句集中在一起运行,例如
package main
import "fmt"
func main() {
defer func() {
fmt.Println("world")
fmt.Println("finished")
}()
fmt.Println("hello")
}
如果一个函数中有多个defer
语句,在函数退出时,这些defer
语句会按照倒序执行,即defer
以类似堆栈的形式存放需要执行的语句。