嵌入的语句不能是声明或标记语句_Go 中的 “简单语句”

7ca66c117d90fee380bf9f4b05b85785.png

https://en.wikipedia.org/wiki/Kiss_(band)

在 Golang 规范中有一个术语:简单语句(simple statement),可能在整个文档中不经常使用,但语言的语法只允许在几个重要的地方使用这些语句。这篇短文的目的就是介绍这些简单语句和可以使用它们的地方。

在规范中,它由 SimpleStmt 产生式定义(使用 EBNF):

SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .

下面我们将介绍 6 种简单语句

1. 空白语句

显然,在简单语句中,空白语句就是什么都不做。

2. 自增或自减语句

x++  // 语义上等价于赋值x + = 1
x--  // x -= 1

在 Go 中,在表达式操作数后用 “--” 或 “++” 构成的不是表达式(译注:Go 中 "--" 或 "++" 不是表达式,而是语句),因此您不会在 .go 源文件中看到让人类似下面纠结的组合:

foo = bar++ + 10

尽管这是一个语句,但是作为简单语句是需要用在有意义的地方并且不会在不应该的地方引入不必要的负担(通过使代码难以阅读和难以维护)。

在 Golang 中没有前缀版本,即在操作对象之前放置 “--” 或 “++”。

3. 发送语句

词法标记 “<-” 表示通过 channel 发送值。它不返回任何值,因此不需要表达它。

4. 表达式语句

某些表达式可以放入语句中。

块是由大括号括起来的一系列语句,例如,表达式语句在如下情况下完全有效。

允许的选项如下:

  • 函数调用(除了一些内置函数,例如 append,cap,complex,imag,len,make,new,real,unsafe.Alignof,unsafe.Offsetof 和unsafe.SizeOf)
  • 方法调用
  • 接收操作符
func (s S) m() {
    fmt.Printf("Hi %sn", s.name)
}

func f(n int) {
    fmt.Printf("f says %dn", n)
}

func main() {
    f(1)
    s := S{"Michał"}
    s.m()
    c := make(chan int)
    go func() {
        c <- 1
    }()
    <-c
    numbers := []int{1, 2, 3}
    len(numbers)  // error: len(numbers) 被执行了但是并未使用
}

5. 赋值语句

大家应该都熟悉一些最基本的赋值形式。首先必须声明变量,右边的表达式必须可以赋值给一个变量:

var population int64
population = 8000000 // 赋值
var city, country string
// 两个单值表达式赋值给两个变量
city, country = "New York", "USA"

当把一个以上的值分配给变量列表时,有两种形式。第一种形式,一个表达式返回多个值,例如函数调用:

f := func() (int64, string) {
    return 2000000, "Paris"
}
var population int64
var city string
population, city = f()

第二种形式是右侧包含有许多表达式, 但每一个是单值的:

population, city = 13000000, "Tokyo"

这两种形式不可以被混淆:

f := func() (int64, string) {
    return 4000000, "Sydney"
}
var population int64
var city, country string
population, city, country = f(), "Australia"

上面这行代码在编译的时候会抛出 "multiple-value f() in single-value context"。

赋值操作是一个由 “=” 符号组成的构造,等号前面是一个二元运算符:

  • 加 (+)
  • 减 (-)
  • 位运算 或 (|)
  • 位运算 异或 (^)
  • 乘 (*)
  • 除 (/)
  • 取余 (%)
  • 位运算 左移 右移 (<< 和 >>)
  • 位运算 与 (&)
  • 位清除 (&^)

a op= b(例如 a += b)在语义上等同于 a = a op b,但 a 只被计算一次。赋值操作也是有效的赋值语句.

6. 简单变量声明

下面是常规变量语句的缩写,它们需要初始化。此外,未明确指定的类型是从初始化语句中使用的类型推断出来的:

s := S{}
a := [...]int{1,2,3}
one, two := f(), g()

现在我们应该很清楚是什么构成了一组有效的简单语句。但是它们用在什么地方呢?

if 语句

简单语句可以选择性地放在条件表达式之前。它经常用于声明变量(使用短变量语句),然后在表达式中使用:

gen := func() int8 {
    return 10
}
if num := gen(); num > 5 {
    fmt.Printf("%d is greater than 5n", num)
}

for 语句

for 语句中的初始化或声明变量只能是简单语句。常见的用法是将短变量声明作为初始声明以及赋值操作或自增/自减语句:

for i := 0; i < 10; i += 1 {
    fmt.Println(i)
}

当然了,也没有东西阻止程序员在这个地方使用其他的简单语句。

switch 语句

与 if 语句类似,可以在 switch 表达式之前将可选的简单语句放入表达式中:

switch aux := 2; letter {
case 'a':
    fmt.Println(aux)
case 'b':
    fmt.Println(aux << 1)
case 'c':
    fmt.Println(aux << 2)
default:
    fmt.Println("no match")
}

或者在 type switch 的守卫前面:

type I interface {
    f(num int8) int8
}
type T1 struct{}
func (t T1) f(num int8) int8 {
    return 1
}
type T2 struct{}
func (t T2) f(num int8) int8 {
    return 2
}
...
var i I = T1{}
switch aux := 10; val := i.(type) {
case nil:
    fmt.Printf("nil %T %dn", val, aux)
case T1:
    fmt.Printf("T1 %T %dn", val, aux)
case T2:
    fmt.Printf("T2 %T %dn", val, aux)
}

它的输出为:

T1 main.T1 10

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值