关键字
关键字是一门语言预定义的单词,作用是帮助编译器理解和解析源码。
如果查资料会说java有53个关键字,go只有25个关键字。go在标榜自己语法简单时,也经常拿这个说事。
但是,仔细看下会发现,java所说的53个关键字包括了11种基本类型和2个保留字。而go的25个关键字却是剔除了基本类型。所有具体来对比应该是40Vs25。
Java
关键字类别 | 关键字 | 关键字含义 |
---|---|---|
访问控制 | private | 一种访问控制方式:私用模式,访问控制修饰符,可以应用于类、方法或字段(在类中声明的变量) |
protected | 一种访问控制方式:保护模式,可以应用于类、方法或字段(在类中声明的变量)的访问控制修饰符 | |
public | 一种访问控制方式:共用模式,可以应用于类、方法或字段(在类中声明的变量)的访问控制修饰符。 | |
类、方法和变量修饰符 | abstract | 表明类或者成员方法具有抽象属性,用于修改类或方法 |
class | 声明一个类,用来声明新的Java类 | |
extends | 表明一个类型是另一个类型的子类型。对于类,可以是另一个类或者抽象类;对于接口,可以是另一个接口 | |
final | 用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量 | |
implements | 表明一个类实现了给定的接口 | |
interface | 接口 | |
native | 用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的 | |
new | 用来创建新实例对象 | |
static | 表明具有静态属性 | |
strictfp | 精确浮点数运算。基本没用过。 | |
synchronized | 表明一段代码需要同步执行 | |
transient | 声明不用序列化的成员域 | |
volatile | 表明两个或者多个变量必须同步地发生变化 | |
程序控制 | break | 提前跳出一个块 |
continue | 回到一次循环的开始处 | |
return | 从成员方法中返回数据 | |
do | 用在do-while循环结构中 | |
while | 用在循环结构中 | |
if | 条件语句的判断 | |
else | 用在条件语句中,表明当条件不成立时的分支 | |
for | 循环 | |
instanceof | 用来测试一个对象是否是指定类型的实例对象 | |
switch | 分支语句结构的引导词 | |
case | 用在switch语句之中,表示其中的一个分支 | |
default | 默认,例如:用在switch语句中,表明一个默认的分支。Java8 中也作用于声明接口函数的默认实现 | |
错误处理 | try | 尝试一个可能抛出异常的程序块 |
catch | 用在异常处理中,用来捕捉异常 | |
throw | 抛出一个异常 | |
throws | 声明在当前定义的成员方法中所有需要抛出的异常 | |
包相关 | import | 表明要访问指定的类或包 |
package | 包 | |
变量引用 | super | 表明当前对象的父类型的引用或者父类型的构造方法 |
this | 指向当前实例对象的引用,用于引用当前实例 | |
void | 声明当前成员方法没有返回值,void可以用作方法的返回类型,以指示该方法不返回值 | |
保留字 | goto | 保留关键字,没有具体含义 |
const | 保留关键字,没有具体含义,是一个类型修饰符,使用const声明的对象不能更新 |
Go
类别 | 关键字 | 含义 |
---|---|---|
类、方法和变量修饰符 | chan | 定义一个channel |
interface | 定义接口 | |
func | 函数定义 | |
map | map结构类型 | |
struct | 定义结构体 | |
type | 定义类型 | |
var | 声明变量 | |
const | 声明常量 | |
程序控制 | break | 提前跳出一个块 |
continue | 回到一次循环的开始处 | |
return | 从方法中返回 | |
if | 条件语句的判断 | |
else | 用在条件语句中,表明当条件不成立时的分支 | |
for | 循环 | |
switch | 分支语句结构的引导词 | |
case | 用在switch语句之中,表示其中的一个分支 | |
fallthrough | 如果case带有fallthrough,程序会继续执行下一条case,不会再判断下一条case的值 | |
default | 默认选项,用在switch和select语句种 | |
select | go语言特有的channel选择结构 | |
defer | 延迟执行,函数的收尾工作。在函数结束前执行 | |
go | 并发 | |
goto | 跳转语句 | |
range | 从slice、map等结构中取元素 | |
包相关 | import | 表明要访问指定的类或包 |
package | 包 |
注意点
-
go主要是去掉了的继承实现相关的关键字。
-
去掉了do-while结构,和for功能上重复。
-
go语言中直接将将多线程的实现作为了关键字。也可见go的并发编程是他的杀手锏。
-
go去掉了异常处理相关的。
几个陌生的关键字
go中有几个关键字还是比较陌生,先简单看下,以后也会专门写文章
go
go中的多线程编程称为goroutine,目前统一译为协程。
在go语言中进行多线程编程非常简单,只要用go关键字后面加上要执行的逻辑,那么这段代码就会以多线程的方式进行。
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 10; i++ {
// 启动协程
go func(i int) {
fmt.Println(i)
}(i)
}
time.Sleep(2 * time.Second)
}
go run .\main.go
9
3
1
2
4
7
8
5
0
6
相比于java的Thread run,go的协程写起来确实简单很多。以后再进行详细对比。
chan
通道。和go协程一样,chan是go进行并发编程的另一个招牌。主要的作用是实现并发同步。大大的降低了并发编程的难度。
go语言的一个设计哲学是
不要通过共享内存来进行多线程通信,而是要通过通信来实现共享内存。
通道机制就是这种设计哲学的一个设计结果。
可以先简单的将通道看作一个先进先出的阻塞队列。
func Test_channel(t *testing.T) {
// 创建一个容量为1的只可以放string类型数据的通道
ch1 := make(chan string, 1)
ch1 <- "a"
// 通道已满,再放会阻塞
// ch1 <- "b"
t.Log("继续执行。。。")
e1 := <-ch1
t.Log("e1:", e1)
// 通道已空,再取会阻塞
e2 := <-ch1
t.Log("e2:", e2)
}
这是一个单元测试函数。
make
在创建chan时用到了make函数,make()函数是go语言的一个内置函数。只用于channel,map和slice的创建。
select
select一般和chan一起使用,目的是为了选择某个通道。
func Test_channel4(t *testing.T) {
// 创建三个通道
intChannels := [3]chan int{
make(chan int, 1),
make(chan int, 1),
make(chan int, 1),
}
// 随机选择一个发送
index := rand.Intn(3)
intChannels[index] <- index
t.Logf("向channe%d发送", index)
select {
case e := <-intChannels[0]:
t.Logf("0接收到:%d", e)
case e := <-intChannels[1]:
t.Logf("1接收到:%d", e)
case e := <-intChannels[2]:
t.Logf("2接收到:%d", e)
default:
t.Log("都没选中")
}
}
定义一个chan数组,随机选择一个通道发送,一旦某个通道有数据了,select会自动选中。
defer
defer相比于前面几个,就很好理解了。
延迟执行,也就是在函数结束前执行,用于执行程序出现运行时错误时的兜底处理。
就是java的try-catch-finally
举个栗子
func main() {
defer func() {
fmt.Println("正常退出")
}()
fmt.Println("=======hello=======")
defer func() {
// 使用go内置函数recover恢复panic
v := recover()
fmt.Println("恐慌被恢复了:", v)
}()
panic("使用panic函数产生一个恐慌!")
fmt.Println("执行不到这里")
}
执行结果
=======hello=======
恐慌被恢复了: 使用panic函数产生一个恐慌!
正常退出
panic()和recover()都是go语言的内建函数
panic()用于手动创建一个运行时错误。recover()专门用于恢复。
recover()必须用在defer延迟里。
网友评论