Go语言的这些地方都做的还不错:
- 拥有自动垃圾回收: 不用手动释放内存
- 一个包系统:
Go 语言的源码复用建立在包(package)基础之上。包通过 package, import, GOPATH 操作完成。
Go 语言的入口 main() 函数所在的包(package)叫 main,main 包想要引用别的代码,需要import导入.
包需要满足:
- 一个目录下的同级文件归属一个包。
- 包名可以与其目录不同名。
- 包名为 main 的包为应用程序的入口包,其他包不能使用
- 包中,通过标识符首字母是否大写,来确定是否可以被导出。首字母大写才可以被导出,视为 public 公共的资源。
-
要引用其他包,可以使用 import 关键字,可以单个导入或者批量导入,语法演示:
// 单个导入 import "package" // 批量导入 import ( "package1" "package2" )
- 导入时,可以为包定义别名:
import ( p1 "package1" p2 "package2" ) // 使用时 p1.Method()
7. import导入时,会从GO的安装目录(也就是GOROOT环境变量设置的目录)和GOPATH环境变量设置的目录中,检索 src/package 来导入包。如果不存在,则导入失败。
GOROOT,就是GO内置的包所在的位置。
GOPATH,就是我们自己定义的包的位置。
8. 可以在源码中,定义 init() 函数。此函数会在包被导入时执行,例如如果是在 main 中导入包,包中存在 init(),那么 init() 中的代码会在 main() 函数执行前执行,用于初始化包所需要的特定资料。
golang的包管理有很大的问题,这个后续有章节单独介绍。
- 函数作为一等公民
支持头等函数(First Class Function)的编程语言,可以把函数赋值给变量,也可以把函数作为其它函数的参数或者返回值。Go 语言支持头等函数的机制
package main import ( "fmt" ) func main() { a := func() { fmt.Println("hello world first class function") } a() fmt.Printf("%T", a) }
在上面的程序中,我们将一个函数赋值给了变量 a
这是把函数赋值给变量的语法。你如果观察得仔细的话,会发现赋值给 a
的函数没有名称。由于没有名称,这类函数称为匿名函数(Anonymous Function)。
输出:
hello world first class function func()
调用一个匿名函数,也可以不赋值。如下是上面使用的简化版本:
package main import ( "fmt" ) func main() { func() { fmt.Println("hello world first class function") }() }
而且还可以给匿名函数传参数呢:
// mainfile package main import ( "fmt" ) func main() { func(n string) { fmt.Println("Welcome", n) }("Gophers") }
输出:
Welcome Gophers
正如我们定义自己的结构体类型一样,我们可以定义自己的函数类型
// mainfile package main import ( "fmt" ) type add func(a int, b int) int func main() { var a add = func(a int, b int) int { return a + b } s := a(5, 6) fmt.Println("Sum", s) }
高阶函数:
满足下列条件之一的函数:
- 接收一个或多个函数作为参数
- 返回值是一个函数
- 词法作用域
- 系统调用接口
- 只读的UTF8字符串
但是Go语言本身只有很少的特性,也不太可能添加太多的特性:
- 它没有隐式的数值转换,
- 没有构造函数和析构函数,
- 没有运算符重载,
- 没有默认参数,
- 也没有继承,
- 没有泛型,
- 没有异常,
- 没有宏,
- 没有函数修饰,
- 更没有线程局部存储