基本语法
Go 程序可以由多个标记组成,可以是关键字,标识符,常量,字符串,符号。如以下 GO 语句由 6 个标记组成:
fmt.Println("Hello, World!")
在 Go 程序中,一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号 ; 结尾,因为这些工作都将由 Go 编译器自动完成。
如果你打算将多个语句写在同一行,它们则必须使用 ; 人为区分,
语法结构
- 包声明
- 引入包
- 函数
- 变量
- 语句 & 表达式
- 注释
package main //定义包名;每一个GO应用都包含一个main的包,标示一个可独立执行的程序 import "fmt" //引入包 func main() { //开始执行函数;main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数 /* 这是我的第一个简单的程序 */ //代理注释,/**/多行注释 //单行注释 fmt.Println("Hello, World!") //字符输出 }
函数定义
函数定义格式:
func function_name( [parameter list] ) [return_types] { 函数体 } //代码案例 /* 函数返回两个数的最大值 */ func max(num1, num2 int) int { /* 声明局部变量 */ var result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
函数定义解析:
func:函数由 func 开始声明
function_name:函数名称,函数名和参数列表一起构成了函数签名。
parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
函数体:函数定义的代码集合。
文件结构
关于包,根据本地测试得出以下几点:
文件名与包名没有直接关系,不一定要将文件名与包名定成同一个。
文件夹名与包名没有直接关系,并非需要一致。
同一个文件夹下的文件只能有一个包名,否则编译报错。
测试代码:
// myMath2.go package mathClass func Sub(x,y int)int{ return x - y } // myMath1.go package mathClass func Add(x,y int)int{ return x + y } // helloworld.go package main import("fmt""./myMath") func main(){ fmt.Println("Hello World!") fmt.Println(mathClass.Add(1,1)) fmt.Println(mathClass.Sub(1,1)) } Test--helloworld.go myMath --myMath1.go --myMath2.go
GO程序执行
直接在命令行中执行
go run hello.go
使用go bulid 生成二进制文件
go build hello.go ./hello
语言变量
Go 语言中变量的声明必须使用空格隔开
var age int; var identifier type
申明多个变量
var identifier1, identifier2 type
package main import "fmt" func main() { var a string = "Runoob" fmt.Println(a) var b, c int = 1, 2 fmt.Println(b, c) }
变量类型
布尔型
数字类型
字符串类型
派生类型
派生类型
指针类型
数组类型
结构化类型 (struct)
Channel 类型
函数类型
切片类型
接口类型 (interface)
Map 类型
Go语言数组声明需要指定元素类型及元素个数,语法如下:
var variable_name [SIZE] variable_type # 代码案例 var balance [10] float32
初始化数组
初始化数组中 {} 中的元素个数不能大于 [] 中的数字。
如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:
var balance=[5]float32{1000.0,2.0,3.4,7.1,50.0} var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} balance[4] = 50.0
变量声明
var v_name v_type v_name = value
省略 var, 注意 := 左侧如果没有声明新的变量,就产生编译错误,格式:
var intVal int intVal :=1 // 这时候会产生编译错误 intVal,intVal1 := 1,2 // 此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句
Go 语言支持多维数组,以下为常用的多维数组声明方式:
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type var threedim [5][10][4]int
初始化二维数组
多维数组可通过大括号来初始值。以下实例为一个 3 行 4 列的二维数组:
a = [3][4]int{ {0, 1, 2, 3} , /* 第一行索引为 0 */ {4, 5, 6, 7} , /* 第二行索引为 1 */ {8, 9, 10, 11}, /* 第三行索引为 2 */ } a = [3][4]int{ {0, 1, 2, 3} , /* 第一行索引为 0 */ {4, 5, 6, 7} , /* 第二行索引为 1 */ {8, 9, 10, 11}} /* 第三行索引为 2 */
访问二维数组
val := a[2][3] 或 var value int = a[2][3]
Go 语言向函数传递数组
void myFunction(param [10]int) { . . . } void myFunction(param []int) { . . . }
Go 语言变量作用域
作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。
Go 语言中变量可以在三个地方声明:
函数内定义的变量称为局部变量
函数外定义的变量称为全局变量
函数定义中的变量称为形式参数
语言常量
const identifier [type] = value
iota,特殊常量,可以认为是一个可以被编译器修改的常量。
package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "ha" //独立值,iota += 1 e //"ha" iota += 1 f = 100 //iota +=1 g //100 iota +=1 h = iota //7,恢复计数 i //8 ) fmt.Println(a,b,c,d,e,f,g,h,i) }
运算符
运算符优先级
有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:
优先级 运算符
5 * / % << >> & &^
4 + - | ^
3 == != < <= > >=
2 &&
1 ||
条件语句
if语句
if 布尔表达式 {/* 在布尔表达式为 true 时执行 */}
if 布尔表达式 {/* 在布尔表达式为 true 时执行 */}else{/* 在布尔表达式为 false 时执行 */}
switch语句
使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true。
switch var1 {case val1:... fallthrough case val2:...default:...} # switch语句判断值的类型 switch x.(type){case type: statement(s);case type: statement(s);/* 你可以定义任意个数的case */default:/* 可选 */ statement(s);} select 语句 select { case communication clause : statement(s); case communication clause : statement(s); /* 你可以定义任意数量的 case */ default : /* 可选 */ statement(s); }
循环语句
for循环
for循环有3种形式,其中一只使用分号。
和c语言for一样:
for init; condition; post {} //案例代码 sum := 0 for i := 0; i <= 10; i++ { sum += i }
init: 一般为赋值表达式,给控制变量赋初值;
condition: 关系表达式或逻辑表达式,循环控制条件;
post: 一般为赋值表达式,给控制变量增量或减量。
for语句执行过程如下:
1、先对表达式 1 赋初值;
2、判别赋值表达式 init 是否满足给定条件,若其值为真,满足循环条件,则执行循环体内语句,然后执行 post,进入第二次循环,再判别 condition;否则判断 condition 的值为假,不满足条件,就终止for循环,执行循环体外语句。
for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:
for key, value := range oldMap { newMap[key] = value } //案例代码 list=[...]string{"伍","肆","叁","贰","壹"} for i, v := range list { fmt.Printf("%d %d\n", i, v) }
和c语言while一样:
init 和 post 参数是可选的,我们可以直接省略它,类似 While 语句。
for condition {} //代码案例 sum := 1 for ; sum <= 10; { sum += sum } // 这样写也可以,更像 While 语句形式 for sum <= 10{ sum += sum }
和c语言for(;;)一样:
for{} //代码案例 for { sum++ // 无限循环下去 }
循环控制语句
break 语句 经常用于中断当前 for 循环或跳出 switch 语句
continue 语句 跳过当前循环的剩余语句,然后继续进行下一轮循环。
goto 语句 将控制转移到被标记的语句。
goto 语句可以无条件地转移到过程中指定的行。通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能。
goto label; .. . label: statement; // 代码案例 var a int = 10 /* 循环 */ LOOP: for a < 20 { if a == 15 { /* 跳过迭代 */ a = a + 1 goto LOOP } fmt.Printf("a的值为 : %d\n", a) a++ }
Go 语言接口
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] { /* 方法实现*/ }
Go 错误处理
type error interface { Error() string }