Go 语言初探(一)

Hyperledger fabric 项目中使用到 Go 语言编写 ChainCode。 因此就简单的学习一下。Google 提供了一个很好的基础教程,这里做一点基本的笔记。

包的概念和语法应该是源自于 Java。长得实在是像。

导入

入口程序为 main (废话),包的声明如下

1
2
3
4
5
6
7
8
9
10
package main

import (
"fmt"
"math/rand"
)

func main() {
fmt.Println("My favorite number is", rand.Intn(10))
}

上面是推荐的打包导入方式。当然也可以分别导入

1
2
import "fmt"
import "math"

导出名

在 Go 中,首字母大写的名称是被导出的。在导入包之后,你只能访问包所导出的名字,任何未导出的名字是不能被包外的代码访问的。因此 FooFOO 是会被导出到作用域,foo 不会。我感觉这个有点像 Python 里面的包导出机制

函数

定义

讲真这种参数名和类型和 C++ 顺序相反的写法我真是不习惯

1
2
3
func add(x int, y int) int {
return x + y
}

偷懒命名法

对于多个连续的函数形参数,同一类型的可以这么写

1
2
3
func add(x, y int) int {
return x + y
}

多值返回

我爱这个特性。省去了多少丑陋的代码。

1
2
3
func swap(x, y string) (string, string) {
return y, x
}

命名返回值

Go 的返回值可以被命名,并且就像在函数体开头声明的变量那样使用。

而且有一种所谓的裸返回的技巧,最后直接一句 return 就可以了

1
2
3
4
5
func split(sum int) (x int,z int) {
x = sum * 4 / 9
z = sum -3
return
}

变量

1
var c, python, java bool

注意 int 值一般最大64位,但有些平台可能更少

短声明

在函数中可以用简短的定义,用了另外一种语法,省略了 var。算是语法糖吧

1
2
3
4
5
func test()(k int) {
z := 3
k = z
return
}

初始化

1
var i, j int = 1, 2

同时也有类型推断,类似于 C++ 里的 auto 或者 Swift 里的 var

1
2
3
4
5
var c = true
j := c //bool
i := 42 //int
f := 3.14 //float64
g := 0.8 + 0.6i //complex128

当然和 C++ 一样,未制定的执行默认初始化

1
2
3
4
var i int      //默认为0
var f float64 //默认0.0
var b bool //默认false
var s string //默认空字符串

类型转换

这个应该是学的 C++ 版本的转换语法,不过似乎舍弃了 C++ 里面 dynamic_cast/static_cast 等各种花式操作?

1
2
3
var i int = 42
var f float64 = float64(i) //float不能省略
var u uint = uint(f) //uint不能省略

要注意的是,Go 的在不同类型之间的项目赋值时需要显式转换,也就是说没有自动转换这回事情了。我试了一下,下面的代码是不行的

1
2
3
var x int = 3
var y float64 = 4.0
var f float64 = x + y//报错

常量

同 C++ 一样,通过 const 修饰得到常量。但常量不能用 := 定义

1
const Truth = true

go 里面专门提到了数值常量,专门用于存储高精度的值。与变量不同,未指定类型的常量由上下文来决定其类型,也就是说常量的行为反而是和 C/C++ 一致的。个人觉得应该是拿来存自然常数 \(e\) 之类的常量吧。

这里有一个比较有意思的语法, const 修饰一堆变量

1
2
3
4
5
6
7
const (
Big = 1 << 10
Small = Big >> 9
)

var i int = Big
var j float64 = Small