由于之前看过其他脚本语言,此时看服务器端语言go语法时也短短用了半天的时间,如图1所示,是个人学习go语法的目录截图,学习网址:菜鸟网站,为了个人方便学习和记忆,因此写下本篇文章,在本篇文章里我主要是针对目录中的项做以简单的理解并加以示例展示,可能不利于没有任何编程功底的同学学习,本人之前做过C++开发3年,这篇文章仅仅作为个人学习之用,记录的功能可能会比较零散,如果有想系统学习go语法的同学直接上菜鸟网站学习即可。
图1 go语法看点
1、语言教程
Go 是一个开源的编程语言。Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型*服务器的系统编程语言。
2、环境安装
windows下下载msi文件,双击即可安装。安装包下载地址为:https://golang.org/dl/。
3、结构
包声明、引入包、函数、变量、语句 & 表达式、注释。执行go文件使用go run *.go
4、数据类型
布尔、数字、字符串和派送类型(指针、数组、结构体、Channel、函数、切片、接口和Map)。关于派生类型后边会有详细介绍
5、变量
var identifier type。例如:var a [type]= "w3cschool菜鸟教程"
6、常量
const identifier [type] = value。例如:const b string = "abc"
7、运算符
和C++一样
8、条件语句
类似于C++,多一个select语句。select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。switch case分支无break
9、循环语句
类似于C++,多一个goto语句。goto语句将控制转移到被标记的语句。for融合了while功能
1 // The most basic type, with a single condition.
2 i := 1
3 for i <= 3 {
4 fmt.Println(i)
5 i = i + 1
6 }
7
8 // A classic initial/condition/after `for` loop.
9 for j := 7; j <= 9; j++ {
10 fmt.Println(j)
11 }
12
13 // `for` without a condition will loop repeatedly
14 // until you `break` out of the loop or `return` from
15 // the enclosing function.
16 for {
17 fmt.Println("loop")
18 break
19 }
20
21 // You can also `continue` to the next iteration of
22 // the loop.
23 for n := 0; n <= 5; n++ {
24 if n%2 == 0 {
25 continue
26 }
27 fmt.Println(n)
28 }
10、函数
函数是基本的代码块,用于执行一个任务。Go 语言最少有个 main() 函数。函数支持多个返回值
func function_name( [parameter list] ) [return_types] {
函数体
}
11、变量作用域
局部变量、全局变量和形式参数。形式参数为函数参数
12、数组
和C++一样。例如:var variable_name [SIZE] variable_type,类型写在最后
13、指针
Go 语言的取地址符是 &,一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。指针声明格式:var var_name *var-type,例如:var ip *int /* 指向整型*/,当一个指针被定义后没有分配到任何变量时,它的值为 nil。
14、结构体
结构体定义需要使用 type 和 struct 语句,结构体的格式如下:
type struct_variable_type struct {
member definition;
member definition;
...
member definition;
}
一旦定义了结构体类型,它就能用于变量的声明,语法格式如下:
variable_name := structure_variable_type {value1, value2...valuen}
15、切片
切片是对数组的抽象。数组的长度不可改变,数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。一个未指定大小的数组来定义切片,例如:var identifier []type,切片不需要说明长度。使用make()函数来创建切片:
var slice1 []type = make([]type, len)
//也可以简写为
slice1 := make([]type, len) //也可以指定容量,其中capacity为可选参数。
make([]T, length, capacity)
16、范围
range 关键字用于for循环中迭代数组(array)、切片(slice)、链表(channel)或集合(map)的元素。在数组和切片中它返回元素的索引值,在集合中返回 key-value 对的 key 值。
nums := []int{, , }
sum :=
for _, num := range nums {
sum += num
}
17、Map
map类似于C++ stl中的map,无序,可以使用内建函数 make 也可以使用 map 关键字来定义 Map:
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type /* 使用 make 函数 */
map_variable = make(map[key_data_type]value_data_type)
如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对
var countryCapitalMap map[string]string
/* 创建集合 */
countryCapitalMap = make(map[string]string)
18、递归函数
函数定义参考10小节函数定义,递归函数同C++中用法一样。以下实例通过 Go 语言的递归函数实例阶乘:
package main import "fmt" func Factorial(x int) (result int) {
if x == {
result = ;
} else {
result = x * Factorial(x - );
}
return;
} func main() {
var i int =
fmt.Printf("%d 的阶乘是 %d\n", i, Factorial(i))
}
19、类型转换
类型转换用于将一种数据类型的变量转换为另外一种类型的变量。形如:type_name(expression)
20、接口
Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
/* 定义接口 */
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
method_name3 [return_type]
...
method_namen [return_type]
} /* 定义结构体 */
type struct_name struct {
/* variables */
} /* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
/* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
/* 方法实现*/
}
使用样例:
package main import (
"fmt"
) type Phone interface {
call()
} type NokiaPhone struct {
} func (nokiaPhone NokiaPhone) call() {
fmt.Println("I am Nokia, I can call you!")
} type IPhone struct {
} func (iPhone IPhone) call() {
fmt.Println("I am iPhone, I can call you!")
} func main() {
var phone Phone phone = new(NokiaPhone)
phone.call() phone = new(IPhone)
phone.call()
}
21、错误处理
Go 语言通过内置的错误接口提供了非常简单的错误处理机制。错误接口理解可以参考上一小节接口来进行理解。使用方法:
package main import (
"fmt"
) // 定义一个 DivideError 结构
type DivideError struct {
dividee int
divider int
} // 实现 `error` 接口
func (de *DivideError) Error() string {
strFormat := `
Cannot proceed, the divider is zero.
dividee: %d
divider:
`
return fmt.Sprintf(strFormat, de.dividee)
} // 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
if varDivider == {
dData := DivideError{ //dData类型根据右侧类型自动判断为error接口
dividee: varDividee,
divider: varDivider,
}
errorMsg = dData.Error()//返回DivideError重写后的Error方法返回值
return
} else {
return varDividee / varDivider, ""
} } func main() { // 正常情况
if result, errorMsg := Divide(, ); errorMsg == "" {
fmt.Println("100/10 = ", result)
}
// 当被除数为零的时候会返回错误信息
if _, errorMsg := Divide(, ); errorMsg != "" {
fmt.Println("errorMsg is: ", errorMsg)
} }
执行以上程序,输出结果为:
/ =
errorMsg is:
Cannot proceed, the divider is zero.
dividee:
divider: