操作符及流程控制
操作符
算术操作符
dart
// +, -, /, *
// 位移操作符,<<,>>,&,|
// ~/ 除号,但是返回值为整数
// % 取模
go
js
// +, -, /, *
// 位移操作符,<<,>>,&,|,~,^
// 指数运算符:x ** y
// 余数运算符:x % y
// 自增运算符:++x 或者 x++
// 自减运算符:--x 或者 x--
python
# +, -, /, *
# 位移操作符,<<,>>,&,|,~,^
# 除法运算 (/) 永远返回浮点数类型
# 使用 // 运算符得到一个整数结果(忽略小数部分)
# 如果要计算余数,可以使用 %
# 使用 ** 运算符来计算乘方
相等大小操作符
dart
- 要测试两个对象代表的是否为同样的内容,使用 == 操作符。
- 两个对象是否是同一个对象, 使用 identical() 方法。
go
比较运算符==
和<
也可以用来比较一个命名类型的变量和另一个有相同类型的变量,
或有着相同底层类型的未命名类型的值之间做比较。
但是如果两个值有着不同的类型,则不能直接进行比较:
var c Celsius
var f Fahrenheit
fmt.Println(c == 0) // "true"
fmt.Println(f >= 0) // "true"
fmt.Println(c == f) // compile error: type mismatch
fmt.Println(c == Celsius(f)) // "true"!
js
python
类型判断操作符
dart
- as 类型转换
- is 如果对象是指定的类型返回 True
- is! 如果对象是指定的类型返回 False
if (emp is Person) { // Type check
emp.firstName = 'Bob';
}
// 使用 as 操作符可以简化上面的代码:
(emp as Person).firstName = 'Bob';
// 上面这两个代码效果是有区别的。
// 如果 emp 是 null 或者不是 Person 类型,
// 则第一个示例使用 is 则不会执行条件里面的代码,
// 而第二个情况使用 as 则会抛出一个异常。
go
js
python
赋值操作符
dart
a = value; // 给 a 变量赋值
b ??= value; // 如果 b 是 null,则赋值给 b;
// 如果不是 null,则 b 的值保持不变
go
js
python
逻辑操作符
dart
- !expr 对表达式结果取反(true 变为 false ,false 变为 true)
- || 逻辑 OR
- && 逻辑 AND
- 只能对布尔值进行判断
go
js
- 能够对所有数据类型进行判断,判断时自动转换为布尔值
// yes
if ('abc' === 'abc') {
console.log('yes')
} else {
console.log('no')
}
// yes
if ('abc' !== 'def') {
console.log('yes')
} else {
console.log('no')
}
// no
if (true && false) {
console.log('yes')
} else {
console.log('no')
}
// yes
if (true || false) {
console.log('yes')
} else {
console.log('no')
}
// yes
if (!false) {
console.log('yes')
} else {
console.log('no')
}
// no
if (0) {
console.log('yes')
} else {
console.log('no')
}
// no
if ('') {
console.log('yes')
} else {
console.log('no')
}
// no
if (undefined) {
console.log('yes')
} else {
console.log('no')
}
// no
if (null) {
console.log('yes')
} else {
console.log('no')
}
// yes
if (!!!null) {
console.log('yes')
} else {
console.log('no')
}
python
# yes
if "abc" == "abc":
print("yes")
else:
print("no")
# yes
if "abc" != "def":
print("yes")
else:
print("no")
# no
if True and False:
print("yes")
else:
print("no")
# yes
if True or False:
print("yes")
else:
print("no")
# yes
if not False:
print("yes")
else:
print("no")
# no
if 0:
print("yes")
else:
print("no")
# no
if "":
print("yes")
else:
print("no")
# no
if []:
print("yes")
else:
print("no")
# no
if None:
print("yes")
else:
print("no")
# yes
if not not not None:
print("yes")
else:
print("no")
位和移位操作符
dart
final value = 0x22;
final bitmask = 0x0f;
assert((value & bitmask) == 0x02); // AND
assert((value & ~bitmask) == 0x20); // AND NOT
assert((value | bitmask) == 0x2f); // OR
assert((value ^ bitmask) == 0x2d); // XOR
assert((value << 4) == 0x220); // Shift left
assert((value >> 4) == 0x02); // Shift right
go
js
python
条件表达式
Conditional expressions(条件表达式)/三元操作符
dart
- condition ? expr1 : expr2 如果 condition 是 true,执行 expr1 (并返回执行的结果); 否则执行 expr2 并返回其结果。
- expr1 ?? expr2 如果 expr1 是 non-null,返回其值; 否则执行 expr2 并返回其结果。
go
js
const x = 2
const y = 3
// even
console.log(x % 2 === 0 ? 'even' : 'odd')
// odd
console.log(y % 2 === 0 ? 'even' : 'odd')
python
x = 2
y = 3
# even
print("even" if x % 2 == 0 else "odd")
# odd
print("even" if y % 2 == 0 else "odd")
级联操作符
dart
级联操作符 (..) 可以在同一个对象上 连续调用多个函数以及访问成员变量。
querySelector('#button') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
// 上面的代码和下面的代码功能一样:
var button = querySelector('#button');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
go
js
python
条件成员访问
dart
?. 和 . 类似,但是左边的操作对象不能为 null, 例如 foo?.bar 如果 foo 为 null 则返回 null,否则返回 bar 成员
go
js
python
流程控制
if
dart
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
go
Go 的 if 语句与 for 循环类似,表达式外无需小括号 ( ) ,而大括号 { } 则是必须的。
package main
import (
"fmt"
"math"
)
func sqrt(x float64) string {
if x < 0 {
return sqrt(-x) + "i"
}
return fmt.Sprint(math.Sqrt(x))
}
func main() {
fmt.Println(sqrt(2), sqrt(-4)) // 1.4142135623730951 2i
}
// 同 for 一样, if 语句可以在条件表达式前执行一个简单的语句。
// 该语句声明的变量作用域仅在 if 之内。
package main
import (
"fmt"
"math"
)
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
return lim
}
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 20),
)
}
// 在 if 的简短语句中声明的变量同样可以在任何对应的 else 块中使用。
package main
import (
"fmt"
"math"
)
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
} else {
fmt.Printf("%g >= %g\n", v, lim)
}
// 这里开始就不能使用 v 了
return lim
}
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 20),
)
}
// 多个条件的时候
if integer == 3 {
fmt.Println("The integer is equal to 3")
} else if integer < 3 {
fmt.Println("The integer is less than 3")
} else {
fmt.Println("The integer is greater than 3")
}
js
python
# 一个 if ... elif ... elif ... 序列
# 可以看作是其他语言中的 switch 或 case 语句的替代
x = int(input("Please enter an integer: "))
if x < 0:
x = 0
print('Negative changed to zero')
elif x == 0:
print('Zero')
elif x == 1:
print('Single')
else:
print('More')
goto
dart
go
用goto跳转到必须在当前函数内定义的标签。
func myFunc() {
i := 0
Here: //这行的第一个词,以冒号结束作为标签
println(i)
i++
goto Here //跳转到Here去
}
js
python
For
dart
var message = new StringBuffer("Dart is fun");
for (var i = 0; i < 5; i++) {
message.write('!');
}
// art for 循环中的闭包会捕获循环的 index 索引值
var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
// 如果不需要当前遍历的索引
candidates.forEach((candidate) => candidate.interview());
// List 和 Set 等实现了 Iterable 接口的类还支持 for-in 形式的 遍历:
var collection = [0, 1, 2];
for (var x in collection) {
print(x);
}
go
Go 只有一种循环结构:for 循环。 初始化语句通常为一句短变量声明,该变量声明仅在 for 语句的作用域中可见。
- 初始化语句:在第一次迭代前执行
- 条件表达式:在每次迭代前求值
- 后置语句:在每次迭代的结尾执行
和 C、Java、JavaScript 之类的语言不同, Go 的 for 语句后面的三个构成部分外没有小括号, 大括号 { } 则是必须的。
// 如同C的for循环
for init; condition; post { }
// 如同C的while循环
for condition { }
// 如同C的for(;;)循环
for { }
package main
import "fmt"
func main() {
sum := 1
for i := 0; i < 10; i++ {
sum *= 2
}
fmt.Println(sum) // 1024
}
// 初始化语句和后置语句是可选的。
// 相当于while循环
package main
import "fmt"
func main() {
sum := 1
for ; sum < 1000; {
sum += sum
}
fmt.Println(sum) // 1024
}
// for 是 Go 中的 “while”
package main
import "fmt"
func main() {
sum := 1
for sum < 1000 {
sum += sum
}
fmt.Println(sum)
}
// 无限循环
// 如果省略循环条件,该循环就不会结束
package main
func main() {
for {
// ...
}
}
// 用牛顿法实现平方根函数
package main
import (
"fmt"
)
func Sqrt(x float64) float64 {
z := 1.8
for n:=0; n<10; n++ {
fmt.Println(z)
z -= (z*z - x) / (2*z)
}
return z
}
func main() {
fmt.Println(Sqrt(2))
}
// 1.8
// 1.4555555555555555
// 1.4148006785411367
// 1.4142136841942816
// 1.4142135623731005
// 1.414213562373095
// 1.4142135623730951
// 1.414213562373095
// 1.4142135623730951
// 1.414213562373095
// 1.4142135623730951
// range 子句能够帮你轻松实现循环
for key, value := range oldMap {
newMap[key] = value
}
// 解析UTF-8, 将每个独立的Unicode码点分离出来
for pos, char := range "日本\x80語" { // \x80 是个非法的UTF-8编码
fmt.Printf("字符 %#U 始于字节位置 %d\n", char, pos)
}
// 反转 a
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}
js
python
# Measure some strings:
words = ['cat', 'window', 'defenestrate']
for w in words:
print(w, len(w))
# 如果在循环内需要修改序列中的值(比如重复某些选中的元素),推荐你先拷贝一份副本。
for w in words[:]: # Loop over a slice copy of the entire list.
if len(w) > 6:
words.insert(0, w)
# ['defenestrate', 'cat', 'window', 'defenestrate']
# 如果写成 for w in words:,这个示例就会创建无限长的列表,
# 一次又一次重复地插入 defenestrate。
range
dart
go
for 循环的 range 形式可遍历切片或映射。 当使用 for 循环遍历切片时,每次迭代都会返回两个值。
- 第一个值为当前元素的下标,
- 第二个值为该下标所对应元素的一份副本。
package main
import "fmt"
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
}
// 2**0 = 1
// 2**1 = 2
// 2**2 = 4
// 2**3 = 8
// 2**4 = 16
// 2**5 = 32
// 2**6 = 64
// 2**7 = 128
// 可以将下标或值赋予 _ 来忽略它。
package main
import "fmt"
func main() {
pow := make([]int, 5)
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
for _, value := range pow {
fmt.Printf("%d\n", value)
}
}
// 1
// 2
// 4
// 8
// 16
// Go语言的range循环在处理字符串的时候,会自动隐式解码UTF8字符串。
for i, r := range "Hello, 世界" {
fmt.Printf("%d\t%q\t%d\n", i, r, r)
}
// 0 'H' 72
// 1 'e' 101
// 2 'l' 108
// 3 'l' 108
// 4 'o' 111
// 5 ',' 44
// 6 ' ' 32
// 7 '世' 19990
// 10 '界' 30028
js
python
# 内置函数 range() 会派上用场。它生成算术级数:
>>> for i in range(5):
... print(i)
...
0
1
2
3
4
# range也可以以另一个数字开头,或者以指定的幅度增加
range(5, 10)
5, 6, 7, 8, 9
range(0, 10, 3)
0, 3, 6, 9
range(-10, -100, -30)
-10, -40, -70
# 要以序列的索引来迭代,您可以将 range() 和 len() 组合如下:
# 然而,在大多数这类情况下,使用 enumerate() 函数比较方便
>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
... print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb
# range 返回的是一个可迭代对象
>>> print(range(10))
range(0, 10)
>>> list(range(5))
[0, 1, 2, 3, 4]
While
dart
while (!isDone()) {
doSomething();
}
do {
printLine();
} while (!atEndOfPage());
go
js
python
BreakContinue
dart
// 使用 break 来终止循环:
while (true) {
if (shutDownRequested()) break;
processIncomingRequests();
}
// 使用 continue 来开始下一次循环:
for (int i = 0; i < candidates.length; i++) {
var candidate = candidates[i];
if (candidate.yearsExperience < 5) {
continue;
}
candidate.interview();
}
// 上面的代码在实现 Iterable 接口对象上可以使用下面的写法:
candidates.where((c) => c.yearsExperience >= 5)
.forEach((c) => c.interview());
go
js
// 1
// 2
// Fizz
// 4
// Buzz
for (let i = 1; i <= 100; i = i + 1) {
if (i === 3) {
console.log('Fizz')
continue
}
if (i === 5) {
console.log('Buzz')
break
}
console.log(i)
}
python
# 1
# 2
# Fizz
# 4
# Buzz
for number in range(1, 101):
if number == 3:
print("Fizz")
continue
if number == 5:
print("Buzz")
break
print(number)
# 循环语句可能带有一个 else 子句;
# 它会在循环遍历完列表 (使用 for) 或是在条件变为假 (使用 while) 的时候被执行,
# 但是不会在循环被 break 语句终止时被执行。
# 当和循环一起使用时,else 子句与 try 语句中的 else 子句的共同点多于 if 语句中的子句:
# try 语句中的 else 子句会在未发生异常时执行,
# 而循环中的 else 子句则会在未发生 break 时执行。
# 计算质数(素数)
>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print(n, 'equals', x, '*', n//x)
... break
... else: # else 子句属于 for 循环, 不属于 if 语句。
... # loop fell through without finding a factor
... print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
# continue 语句也是借鉴自 C 语言,表示继续循环中的下一次迭代:
>>> for num in range(2, 10):
... if num % 2 == 0:
... print("Found an even number", num)
... continue
... print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
pass
dart
go
js
python
while True:
pass # Busy-wait for keyboard interrupt (Ctrl+C)
class MyEmptyClass:
pass
def initlog(*args):
pass # Remember to implement this!
Switch
dart
Dart 中的 Switch 语句使用 == 比较 integer、string、或者编译时常量。 比较的对象必须都是同一个类的实例(并且不是 其子类)
每个非空的 case 语句都必须有一个 break 语句。 另外还可以通过 continue、 throw 或 者 return 来结束非空 case 语句。 当没有 case 语句匹配的时候,可以使用 default 语句来匹配这种默认情况。
var command = 'OPEN';
switch (command) {
case 'CLOSED':
executeClosed();
break;
case 'PENDING':
executePending();
break;
case 'APPROVED':
executeApproved();
break;
case 'DENIED':
executeDenied();
break;
case 'OPEN':
executeOpen();
break;
default:
executeUnknown();
}
// 在 Dart 中的空 case 语句中可以不要 break 语句:
var command = 'CLOSED';
switch (command) {
case 'CLOSED': // Empty case falls through.
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
// 使用 continue 语句跳转到对应的标签(label)处继续执行
var command = 'CLOSED';
switch (command) {
case 'CLOSED':
executeClosed();
continue nowClosed;
// Continues executing at the nowClosed label.
nowClosed:
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}
go
switch 是编写一连串 if - else 语句的简便方法。 它运行第一个值等于条件表达式的 case 语句。
Go 只运行选定的 case,而非之后所有的 case。 Go 自动提供了在这些语言中每个 case 后面所需的 break 语句。 除非以 fallthrough 语句结束,否则分支会自动终止。 Go 的另一点重要的不同在于 switch 的 case 无需为常量,且取值不必为整数。
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Print("Go runs on ")
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
case "linux":
fmt.Println("Linux.")
default:
// freebsd, openbsd,
// plan9, windows...
fmt.Printf("%s.\n", os)
}
}
// Go runs on Linux.
// switch 的 case 语句从上到下顺次执行,直到匹配成功时停止。
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("When's Saturday?")
fmt.Println(time.Now())
fmt.Println(time.Saturday)
today := time.Now().Weekday()
switch time.Saturday {
case today + 0:
fmt.Println("Today.")
case today + 1:
fmt.Println("Tomorrow.")
case today + 2:
fmt.Println("In two days.")
default:
fmt.Println("Too far away.")
}
}
// When's Saturday?
// 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
// Saturday
// Too far away.
// 没有条件的 switch 同 switch true 一样。
// 这种形式能将一长串 if-then-else 写得更加清晰。
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(t)
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
}
func unhex(c byte) byte {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
// switch 并不会自动下溯,但 case 可通过逗号分隔来列举相同的处理条件。
func shouldEscape(c byte) bool {
switch c {
case ' ', '?', '&', '=', '#', '+', '%':
return true
}
return false
}
js
python
defer
dart
go
defer 语句会将函数推迟到外层函数返回之后执行。 推迟调用的函数其参数会立即求值, 但直到外层函数返回前该函数都不会被调用。
推迟的函数调用会被压入一个栈中。 当外层函数返回时,被推迟的函数会按照后进先出的顺序调用。
defer语句经常被用于处理成对的操作, 如打开、关闭、连接、断开连接、加锁、释放锁。通过defer机制
package main
import "fmt"
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
// hello
// world
// defer 栈
package main
import "fmt"
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
}
// counting
// done
// 9
// 8
// 7
// 6
// 5
// 4
// 3
// 2
// 1
// 0
// Contents 将文件的内容作为字符串返回。
func Contents(filename string) (string, error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close() // f.Close 会在我们结束后运行。
var result []byte
buf := make([]byte, 100)
for {
n, err := f.Read(buf[0:])
result = append(result, buf[0:n]...) // append 将在后面讨论。
if err != nil {
if err == io.EOF {
break
}
return "", err // 我们在这里返回后,f 就会被关闭。
}
}
return string(result), nil // 我们在这里返回后,f 就会被关闭。
}
// 对匿名函数采用defer机制,可以使其观察函数的返回值。
func double(x int) (result int) {
defer func() { fmt.Printf("double(%d) = %d\n", x,result) }()
return x + x
}
_ = double(4)
// Output:
// "double(4) = 8"
// 被延迟执行的匿名函数甚至可以修改函数返回给调用者的返回值:
func triple(x int) (result int) {
defer func() { result += x }()
return double(x)
}
fmt.Println(triple(4)) // "12"
js
python