摘要:go入门相关内容,参考:Go入门指南,主要总结其中:一到五章的内容。
一、基本概念
1、包相关
①第一种形式
1 | import "fmt" |
②第二种形式
1 | import ( |
2、基本类型
- 布尔类型:bool
- 整数:int、int8、int16、int32、int64
- 无符号整数:uint、uint8、uint16、uint32、uint64
- 字节:byte(和 uint8 等价)
- Unicode:rune(和 int32 等价)
- 整数指针:uintptr(存储 uint32、uint64 的指针)
- 浮点数:float32、float64
- 复数:complex64、complex128
- 字符串类型:string
- 值类型:array(数组)、struct(结构化变量)
- 引用类型:slice(动态数组)、map、channel(管道)
- 接口:interface
- 函数:function
3、函数相关
函数执行顺序:init —》main
测试代码如下所示:
1 |
|
4、类型转换
在必要以及可行的情况下,一个类型的值可以被转换成另一种类型的值。由于 Go 语言不存在隐式类型转换,因此所有的转换都必须显式说明,就像调用一个函数一样(类型在这里的作用可以看作是一种函数):
1 | valueOfTypeB = typeB(valueOfTypeA) |
例如:
1 | var a = 5.0 |
5、Go 程序的一般结构
一般结构如下:
- 在完成包的 import 之后,开始对常量、变量和类型的定义或声明。
- 如果存在 init 函数的话,则对该函数进行定义(这是一个特殊的函数,每个含有该函数的包都会首先执行这个函数)。
- 如果当前包是 main 包,则定义 main 函数。
- 然后定义其余的函数,首先是类型的方法,接着是按照 main 函数中先后调用的顺序来定义相关函数,如果有很多函数,则可以按照字母顺序来进行排序。
例子:
1 | package main |
6、常量、变量
①常量
常量使用关键字 const 定义,用于存储不会改变的数据。
存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
常量的定义格式:
1 | const identifier [type] = value |
②常量枚举
例子如下所示:
1 | const ( |
iota 可以被用作枚举值,第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1,例子如下所示:
1 | const ( |
②变量
声明变量的一般形式是使用 var 关键字,例子如下所示:
1 | var identifier type |
7、运算符
有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:
1 | 优先级 运算符 |
8、字符串
字符串是一种值类型,且值不可变,即创建某个文本后你无法再次修改这个文本的内容;更深入地讲,字符串是字节的定长数组。
Go 支持以下 2 种形式的字面值:
解释字符串:
该类字符串使用双引号括起来,其中的相关的转义字符将被替换,这些转义字符包括:
1 | \n:换行符 |
非解释字符串:
该类字符串使用反引号括起来,支持换行,例如:
1 | `This is a raw string \n` 中的 `\n\` 会被原样输出。 |
9、时间和日期
1 | package main |
10、指针
Go 语言为程序员提供了控制数据结构的指针的能力;但是,你不能进行指针运算。
Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。如下所示:
1 | var i1 = 5 |
Go 语言的存地址符是 *,放到一个变量前使用就会返回相应变量的内存地址。如下所示:
1 | var intP *int = &i1 |
一个指针变量可以指向任何一个值的内存地址 它指向那个值的内存地址,在 32 位机器上占用 4 个字节,在 64 位机器上占用 8 个字节,并且与它所指向的值的大小无关。
当然,可以声明指针指向任何类型的值来表明它的原始性或结构性;你可以在指针类型前面加上 * 号(前缀)来获取指针所指向的内容,这里的 * 号是一个类型更改器。使用一个指针引用一个值被称为间接引用。
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
一个指针变量通常缩写为 ptr。
注意事项
1 | 1、在书写表达式类似 var p *type 时,切记在 * 号和指针名称间留有一个空格. |
例子一:
1 | package main |
例子二:
1 | package main |
例子三:
对一个空指针的反向引用是不合法的,并且会使程序崩溃:
1 | package main |
二、控制结构
- if-else 结构
- 多返回值函数
- switch 结构
- for (range) 结构
- 标签与 goto
- select 结构,用于 channel 的选择
1、if-else 结构
关键字 if 和 else 之后的左大括号 { 必须和关键字在同一行,如果你使用了 else-if 结构,则前段代码块的右大括号 } 必须和 else-if 关键字在同一行。这两条规则都是被编译器强制规定的。
如下所示:
1 | if condition1 { |
if 可以包含一个初始化语句(如:给一个变量赋值)。这种写法具有固定的格式(在初始化语句后方必须加上分号):
1 | if initialization; condition { |
但要注意的是,使用简短方式 := 声明的变量的作用域只存在于 if 结构中(在 if 结构的大括号之间,如果使用 if-else 结构则在 else 代码块中变量也会存在)。
如果变量在 if 结构之前就已经存在,那么在 if 结构中,该变量原来的值会被隐藏。
例子:
1 | package main |
2、多返回值函数
如下所示:
1 | package main |
习惯用法,如下所示:
1 | value, err := pack1.Function1(param1) |
由于本例的函数调用者属于 main 函数,所以程序会直接停止运行。
如果我们想要在错误发生的同时终止程序的运行,我们可以使用 os 包的 Exit 函数,如下所示:
1 | if err != nil { |
或者将 ok-pattern 的获取放置在 if 语句的初始化部分,然后进行判断:
1 | if value, ok := readData(); ok { |
3、switch 结构
Go 语言中的 switch 结构使用上更加灵活。它接受任意形式的表达式:
1 | switch var1 { |
变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。前花括号 { 必须和 switch 关键字在同一行。
一旦成功地匹配到某个分支,在执行完相应代码后就会退出整个 switch 代码块,也就是说您不需要特别使用 break 语句来表示结束。
因此,程序也不会自动地去执行下一个分支的代码。如果在执行完每个分支的代码后,还希望继续执行后续分支的代码,可以使用 fallthrough 关键字来达到目的。
1 | switch i { |
使用举例:
1 | 例一: |
4、for (range) 结构
第一种形式
基本形式为:
1 | for 初始化语句; 条件语句; 修饰语句 {} |
例子:
1 | package main |
第二种形式
基本形式为:
1 | for 条件语句 {} |
例子:
1 | package main |
第三种形式
无限循环,基本形式为:
1 | for { } |
第四种形式
for-range 结构,一般形式为:
1 | for ix, val := range coll { |
要注意的是,val 始终为集合中对应索引的值拷贝,因此它一般只具有只读性质,对它所做的任何修改都不会影响到集合中原有的值(译者注:如果 val 为指针,则会产生指针的拷贝,依旧可以修改集合中的原值)。
一个字符串是 Unicode 编码的字符(或称之为 rune)集合,因此您也可以用它迭代字符串:
1 | package main |
5、标签与 goto
for、switch 或 select 语句都可以配合标签(label)形式的标识符使用,即某一行第一个以冒号(:)结尾的单词(gofmt 会将后续代码自动移至下一行)。
例子:
1 | package main |
continue 语句指向 LABEL1,当执行到该语句的时候,就会跳转到 LABEL1 标签的位置。
您可以看到当 j==4 和 j==5 的时候,没有任何输出:标签的作用对象为外部循环,因此 i 会直接变成下一个循环的值,而此时 j 的值就被重设为 0,即它的初始值。
如果将 continue 改为 break,则不会只退出内层循环,而是直接退出外层循环了。
注意:
- 标签的名称是大小写敏感的,为了提升可读性,一般建议使用全部大写字母
例子二:
1 | package main |
- 本文作者: th3ee9ine
- 本文链接: https://www.blog.ajie39.top/2022/03/06/Go入门总结(一)/
- 版权声明: 本博客所有文章除特别声明外,均采用 LICENSE 下的许可协议。转载请注明出处!