【go入门】go关键字

860 阅读6分钟

关键字

关键字是一门语言预定义的单词,作用是帮助编译器理解和解析源码。

如果查资料会说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函数定义
mapmap结构类型
struct定义结构体
type定义类型
var声明变量
const声明常量
程序控制break提前跳出一个块
continue回到一次循环的开始处
return从方法中返回
if条件语句的判断
else用在条件语句中,表明当条件不成立时的分支
for循环
switch分支语句结构的引导词
case用在switch语句之中,表示其中的一个分支
fallthrough如果case带有fallthrough,程序会继续执行下一条case,不会再判断下一条case的值
default默认选项,用在switch和select语句种
selectgo语言特有的channel选择结构
defer延迟执行,函数的收尾工作。在函数结束前执行
go并发
goto跳转语句
range从slice、map等结构中取元素
包相关import表明要访问指定的类或包
package

注意点

  1. go主要是去掉了的继承实现相关的关键字。
  2. 去掉了do-while结构,和for功能上重复。
  3. go语言中直接将将多线程的实现作为了关键字。也可见go的并发编程是他的杀手锏。
  4. 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延迟里。