Getting Started
-
安装
-
开发环境
使用学生认证下载 JetBrains GoLand,或者 VSCode 安装插件。 GoLand 由鼎鼎大名的 JetBrains 公司,出品,其推出的 Java IDE:IDEA,可以说是 Java 开发中的最强 IDE,所以这里还是首推 GoLand 进行开发,在 JetBrains 官网注册账号后可以使用 edu 教育邮箱进行学生认证,获取一年的 JetBrains 全家桶,包含 IDEA,PyCharm,GoLand,CLion 等产品。 如果不想麻烦,也可以选择 VSCode,并安装 Go 语言支持包,结合 VSCode 自身提供的插件市场,可以配置成自己顺手的开发环境。
-
配置镜像源
由于众所周知的原因,建议还是配上国内的镜像,避免网络问题。
-
参考资料
-
环境配置
关于 Go 语言的环境变量配置问题,我们在以后得 Go Module 中再进行探讨,这里我们先记住如果你安装的是最新的 Go 1.20 版本,那么如果项目存在
go.mod,项目默认是采用module-aware的形式。在上边第3步时如果配置了GO11MODULE=on,以往的GOPATH则不再是存放项目源码的位置,但是GOPATH对应的目录仍然用来存储下载的依赖,并且存放在了GOPATH/pkg/mod目录下。然后我们可以创建练习项目。
大家可能会疑惑为什么可以有多个main.go,多个main function,在还不了解 Go 模块的原理前,我们可以先按照这样的结构构建我们自己的学习项目。
至此我们完成了基本的环境配置,下边我们就可以学习基本的语法了。
Go 语言介绍
Go 项目包括编程语言本身,附带了相关的工具和标准库,最后但并非代表不重要的是,关于简洁编程哲学的宣言。就事后诸葛的角度来看,Go 语言的这些地方都做的还不错:
- 拥有自动垃圾回收
- 一个包系统
- 函数作为一等公民
- 词法作用域
- 系统调用接口
- 只读的 UTF8 字符串等
但是 Go 语言本身只有很少的特性,也不太可能添加太多的特性。例如,它
- 没有隐式的数值转换
- 没有构造函数和析构函数
- 没有运算符重载
- 没有默认参数
- 没有继承 // Go 采用组合的思想
- 没有泛型 // 1.18后支持了
- 没有异常 // 无 Exception 机制,但是有 Error 机制
- 没有宏
- 没有函数修饰
- 没有线程局部存储
数据类型
Go 语言将数据类型分为四类:
- 基础类型:数字、字符串和布尔型
- 复合类型:数组和结构体——是通过组合简单类型,来表达更加复杂的数据结构。
- 引用类型:指针
*T、切片slice、字典map、函数func(tion)、通道chan(nel),对程序中一个变量或状态间接引用。这意味着对任一引用类型数据的修改都会影响所有该引用的拷贝。 - 接口类型:只能定义方法,不能包含数据的特殊类型,其他类型通过实现接口定义的方法实现接口
interface。
注意这里的复合类型不同于引用类型,可能我们会习惯性的认为像Java一样,我们定义的类型示例也是引用,但是其实还是值类型,在赋值和函数调用时都是值传递。
枚举类型
Go 语言中没有其他语言中的枚举类型,要实现枚举类型,可以使用 itoa 常量生成器。
// 定义 Color 类型
type Color int
const (
Red Color = iota
Green
Blue
Yellow
Pink
)
声明
Go 中包含 4 种声明:
var:变量声明const:常量声明type:类型声明func:函数声明
从包的角度,又分为两种:
- 函数内声明
- 包级声明
包一级的声明没有顺序之分,前面定义的函数也可以调用后面定义的函数。
英文小写字母开头的变量表示不导出,大写字母开头的表示导出。 中文开始的变量表示不导出。
函数是一等公民,类似于 Javascript,函数值与变量一样都是可以引用的。
变量
变量声明格式
var 变量名 类型 = 初始值
其中类型和初始值可以省略其一,Go 可以自动进行类型推断或者执行默认初始化,对特定类型的变量赋予对应的默认零值。
可以同时声明多个变量,可以是同一类型,也可以是不同类型,还可以接受函数的多个返回值声明多个变量,这一点和 Python 比较像。
简短变量声明
在函数内部,声明一个局部变量时,往往使用简短变量声明的形式。
变量名 := 表达式
变量的类型根据表达式来自动推导。并且可以像正常变量声明一样,支持多个变量的同时声明。
简短变量声明往往用于 for 循环语句的初始化语句。
注意区别:=与=,:=是声明,=是赋值。
简短变量声明中至少要有一个新的变量。
简短变量声明的变量会覆盖外部词法域声明的变量。
i, j = j, i // 元组赋值,交换 i 和 j 的值,类似于 Python
类型
一个类型声明语句创建了一个新的类型名称,和现有类型具有相同的底层结构。新命名的类型提供了一个方法,用来分隔不同概念的类型,这样即使它们底层类型相同也是不兼容的。
type 类型名字 底层类型
类型声明语句一般出现在包一级,因此如果新创建的类型名字的首字符大写,则在包外部也可以使用。
和定义新类型相似,我们可以多加一个=来声明一个类型别名。
type 类型别名 = 底层类型
这样得到的只是一个类型别名,与底层类型仍然是兼容的。
type FooInt int
type BarInt = int
var a FooInt = 10
var b BarInt = 20
fmt.Printf("type of a is %T", a) // FooInt
fmt.Printf("type of b is %T", b) // int
对于每一个类型 T,都有一个对应的类型转换操作 T(x),用于将 x 转为 T 类型
如果 T 是指针类型,可能会需要用小括弧包装 T,比如
(*int)(0)只有当两个类型的底层基础类型相同时,才允许这种转型操作,或者是两者都是指向相同底层结构的指针类型,这些转换只改变类型而不会影响值本身。如果 x 是可以赋值给 T 类型的值,那么 x 必然也可以被转为 T 类型,但是一般没有这个必要。
指针
接触过 C/C++ 的朋友肯定对此不会陌生,指针很强大,但是也很麻烦,于是 Go 对 C/C++ 中的指针进行了限制,不能进行指针的运算,而且贴心的增加了垃圾回收机制,再也不用担心 new 与 free 了。
在创建类型实例时,Go 提供了两个内置方法:new() 和 make()。
由于 new 只是一个预定义的函数,它并不是一个关键字,因此我们可以将 new 重新定义为别的类型,但是强烈建议不要这么做。
new 与 make 的区别
- 二者都是用来做内存分配的。
- make 只用于 slice、map 以及 channel 的初始化,返回的还是这三个引用类型本身
- 而 new 用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。
- 一般对于 slice、map、channel 类型使用 make 函数,而对于 struct 类型使用 new 函数。
函数
Go 语言中使用 func 关键字声明一个函数。
一个典型的函数可能结构类似于下面的示例:
func foo(a int, b string) (int, error) {
// do something to parameters a and b
res, err := strconv.Atoi(b)
if err != nil { // error occured
return a, err
}
// return result and error, both are optional
return a+res, nil
}
注意:
Go 语言不支持默认参数,也不支持用参数名传递参数(类似 Python 那种写法)。
如果一个函数所有的返回值都有显式的变量名,那么该函数的 return 语句可以省略操作数。这称之为 bare return。
Go 使用控制流机制(如 if 和 return)处理错误,这使得编码人员能更多的关注错误处理。
好了,以上就是笔者在学习时记录的关于 Go 语言的基础内容,如有错误,欢迎评论区留言批评指正,大家一起学习一起进步!