Go 语言入门指南:基础语法和常用特性解析
概述
本文将对go语言基础语法和特性做分析,同时作者有java开发的经验,会把java基础语法和go语法作对比,展示语言各自特点,让掌握java基础的同学更方便快速的掌握go语言。
java和go的共性与特性
- go语言是一种命令式语言,java是一种声明式语言。
- go启动程序很快,java相对较长。
- go语法简单开发效率高,java相对较低。
- go语言部署简单,java相对复杂。
- java和go都是自动垃圾回收机制
- java和go都可以跨平台。
go语言语法
梦开始的地方
众所周知,"hello world"被称为梦开始的地方,所以,本人将从"hello world"带大家初识go语言。
js
package main
import "fmt" --告诉go需要的包
func main() {
/* 这是我的第一个简单的程序 */ --注释
fmt.Println("Hello, World!") --输出语句
}
- 对于以上代码,第一步指明了文件属于哪个包,这里注意每个go应包含main()
- 这里是告诉go语言需要的包,这里需要注意的是Java中的package实际上就可以理解为文件名,"import"导入的是包中(文件中)的某个类;而go总的package不是指文件,但一个文件中只能有一个package,一个package可以组织多个 ".go"源文件,"import"导入的是文件而不是包,而程序中实际使用的是包。
- 执行函数,这里注意main()执行函数是必须的。
- 注释,这里注释和java注释一样,函数执行被忽略。
变量与常量
Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。
声明变量的一般形式是使用 var 关键字
js
var identifier type
当然还有一种简洁的写法
js
f := "Runoob" // var f string = "Runoob"
但是这里需要注意的是,如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误
js
var intVal int
intVal :=1 // 这时候会产生编译错误,因为 intVal 已经声明,不需要重新声明
常量定义格式
js
const identifier [type] = value
java的变量前面必须有类型,而go语言就可以用一个var或者:=声明其他类型,简化开发效率。
go语言语句
go语言条件语句
js
if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
} else {
/* 在布尔表达式为 false 时执行 */
}
这里需要注意的是,go语言没有三目运算符。
go语言循环语句
js
for{}
go语言的循环语句很简单便利,在java中的while和do..while在go语言中都没有,for不需要小括号,但是需要注意的是在java中单行可以取消大括号,go语言则必须要大括号 。
另外,Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对,下面一个例子说明
js
for key, value := range oldMap {
newMap[key] = value
}
函数与指针
这里我们先讲指针的概念:
Go 语言的取地址符是 &,取值则为*,我们看下面的例子
js
package main
import "fmt"
func main() {
var a int= 20 /* 声明实际变量 */
var ip *int /* 声明指针变量 */
ip = &a /* 指针变量的存储地址 */
fmt.Printf("a 变量的地址是: %x\n", &a )
/* 指针变量的存储地址 */
fmt.Printf("ip 变量储存的指针地址: %x\n", ip )
/* 使用指针访问值 */
fmt.Printf("*ip 变量的值: %d\n", *ip )
}
a 变量的地址是: 20818a220
ip 变量储存的指针地址: 20818a220
*ip 变量的值: 20
通过上面例子相信你已经很清楚的了解指针了,下面我们将讲解H函数的概念已经指针在函数中使用注意事项:
Go语言函数定义格式
func function_name( [parameter list] ) [return_types] { 函数体 }
上面第一个中括号为实际参数(当函数被调用时,你可以将值传递给参数)第二个为返回参数,函数返回一列值。 这里需要注意的就是java的返回值只能是单一值,而go可以返回多值。
指针在函数中使用比较特殊,所以单独放一个例子说明:
js
package main
import "fmt"
func add2(n int) {
n += 2
}
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 5
add2(n)
fmt.Println(n) // 5
add2ptr(&n)
fmt.Println(n) // 7
}
上述代码重点是在执行add2ptr(&n)传入的参数必须带有&。
数组 切片 Map(集合) 结构体
数组
数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,在数组里面,要注意他的类型是固定的,下面说明声明数组以及初始化的方式
js
var balance [10]float32
var numbers [5]int
var numbers = [5]int{1, 2, 3, 4, 5}
numbers := [5]int{1, 2, 3, 4, 5}
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
或
balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
上述代码第一句为声明,其他为注释。
切片
切片是一个可变长度的数组,这点和java中的集合类似,但是java中集合可以储存不同类型,切片只能是同类型的,下面展示声明切片和初始化切片
js
var identifier []type
var slice1 []type = make([]type, len)
也可以简写为
slice1 := make([]type, len)
初始化
s :=[] int {1,2,3 }
s := arr[:]
s := arr[startIndex:endIndex]
Map
Map 是一种无序的键值对的集合。
Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。 在java中Map的底层是红黑二叉树,go的底层则是Hash表。
下面一个实例教你使用Map
js
package main
import "fmt"
func main() {
var siteMap map[string]string /*创建集合 */
siteMap = make(map[string]string)
/* map 插入 key - value 对,各个国家对应的首都 */
siteMap [ "Google" ] = "谷歌"
siteMap [ "Runoob" ] = "菜鸟教程"
siteMap [ "Baidu" ] = "百度"
siteMap [ "Wiki" ] = "维基百科"
/*使用键输出地图值 */
for site := range siteMap {
fmt.Println(site, "首都是", siteMap [site])
}
/*查看元素在集合中是否存在 */
name, ok := siteMap [ "Facebook" ] /*如果确定是真实的,则存在,否则不存在 */
/*fmt.Println(capital) */
/*fmt.Println(ok) */
if (ok) {
fmt.Println("Facebook 的 站点是", name)
} else {
fmt.Println("Facebook 站点不存在")
}
}
结构体
在结构体中我们可以为不同项定义不同的数据类型,这点既可以相当于java的一个对象,下面是定义结构体
js
type struct_variable_type struct {
member definition
member definition
...
member definition
}
访问结构体和java里面通过对象.属性类似,结构体.成员名"
。
接口
Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
接口可以让我们将不同的类型绑定到一组公共的方法上,从而实现多态和灵活的设计。
Go 语言中的接口是隐式实现的,也就是说,如果一个类型实现了一个接口定义的所有方法,那么它就自动地实现了该接口。因此,我们可以通过将接口作为参数来实现对不同类型的调用,从而实现多态。 下面一个实例很好的演示接口使用
js
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()
}
在上面的例子中,我们定义了一个接口 Phone ,接口里面有一个方法 call()。然后我们在 main 函数里面定义了一个 Phone 类型变量,并分别为之赋值为 NokiaPhone 和 IPhone。然后调用 call() 方法,输出结果如下:
js
I am Nokia, I can call you!
I am iPhone, I can call you!
错误处理
Go 语言通过内置的错误接口提供了非常简单的错误处理机制。 java通try..catch结构处理异常,而go语言的error可以直接写在变量后,下面一个实例演示
js
result, err:= Sqrt(-1)
if err != nil {
fmt.Println(err)
}
在下面的例子中,我们在调用 Sqrt 的时候传递的一个负数,然后就得到了 non-nil 的 error 对象,将此对象与 nil 比较,结果为 true,所以 fmt.Println(fmt 包在处理 error 时会调用 Error 方法)被调用,以输出错误。
感悟
在学习go语言的过程中,我感受到了类c语言的强大魅力,不过对于我自身而言,c语言在大一学的,而后来接触更多的是c#和java,所以刚开始学的时候有很多地方很变扭,不过通过学习我也发现他的语法真的比java和c语言简化了好多,适合快速上手,目前对于标准库的一些东西了解不够彻底,后续将逐步学习并且发布文章。
期待我的下一篇文章吧!