后端Go基础语法|青训营笔记

75 阅读9分钟

这是我参与【第五届青训营】伴学笔记创作的第1天

作为一个刚接触go语言的小白,刚学习王克纯老师的第一节课,内心只有一个感受:哇!这就是高手吗?放在大学要讲十几个课时的内容,大佬竟然只需要半个小时就讲完了!虽然王克纯老师讲的很好,课上老师讲的东西都理解了,但是课下再回想的时候,还是有点生疏,所以,废话不多说,复习来一波。进入今天的笔记复习内容。(课上教授内容较多,为了更好的学习与复习,课上讲授的内容将分为数篇来记录)

一、Go语言的基础结构

与Go的初次相遇是很美好的,它向我热情地打着招呼:“Hello World!”。

package main
import "fmt"
func main() {
   var arr = "Hello World!"
   /*这是我的第一个简单的程序*/
   fmt.Println(arr)
}

它的基础组成有这么几个部分:

  • 包声明

第一行代码 package main 定义了包名。我们必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main。package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。

  • 引入包

第二行 import "fmt"  告诉 Go 编译器这个程序需要使用 fmt 包(的函数,或其他元素),fmt 包实现了格式化 IO(输入/输出)的函数。

  • 函数

第三行 func main()  是程序开始执行的函数。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数(如果有 init() 函数则会先执行该函数)。

  • 变量

第四行的var arr是声明一个名字为arr的变量并为其赋值为“Hello World!”。Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。声明变量的一般形式是使用 var 关键字,并且一般会对其进行赋值操作。

  • 注释

第五行 /.../ 是注释,在程序执行时将被忽略。单行注释是最常见的注释形式,你可以在任何地方使用以 // 开头的单行注释。多行注释也叫块注释,均已以 /* 开头,并以 */ 结尾,且不可以嵌套使用,多行注释一般用于包的文档描述或注释成块的代码片段。

  • 语句 & 表达式

第六行 fmt.Println(...)  可以将字符串输出到控制台,并在最后自动增加换行字符 \n。

注: 标识符用来命名变量、类型等程序实体。一个标识符实际上就是一个或是多个字母(AZ和a-z)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。

以下是有效的标识符:

myname     abc      my_name   a_123     Myname
myname50   _temp       j      a23b9     retVal

以下是无效的标识符:

  • 123ab(以数字开头)
  • case(Go 语言的关键字)
  • a+b(运算符是不允许的)

二、Go的数据类型

在 Go 编程语言中,数据类型用于声明函数和变量。

数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。

类型描述
布尔型布尔型的值只能是常量 true 或者 false。
数字类型整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。
字符串类型字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
派生类型(a) 指针类型(Pointer)(b) 数组类型(c) 结构化类型(struct) (d) Channel 类型(e) 函数类型 (f) 切片类型 (g) 接口类型(interface)(h) Map 类型

三、Go的语言变量

3.1单变量声明

3.1.1 指定变量类型

如果没有初始化,则变量默认为零值,零值是系统默认设置的值

实例展示:
package main
import "fmt"
func main() {
   // 声明一个变量并初始化
   var a string = "Hello World!"
   fmt.Println(a)
   // 没有初始化就为零值
   var b int
   fmt.Println(b)
   // bool 零值为 false
   var c bool
   fmt.Println(c)
}

输出结果:

Hello World!

0

false

  • 数值类型的零值为 0
  • 布尔类型的零值为 false
  • 字符串的零值为  "" (空字符串)

3.1.2 根据值自行判定变量类型

实例展示:
package main
import "fmt"
func main() {
   var a = "Hello World!"
   fmt.Println(a)
}

输出结果: Hello World!

3.1.3 使用 := 声明变量

实例展示:
package main
import "fmt"
func main() {
   a := "Hello World!"
   fmt.Println(a)
}

输出结果: Hello World!

  • 使用:=是声明变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值
  • 如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误
示例:
package main
import "fmt"
func main() {
   var a string
   a := "Hello World!"
   fmt.Println(a)
}

上面的代码会提示No new variables on the left side of ':=,即定义了同一个变量,产生冲突

3.2 多变量声明

实例展示:
package main
import "fmt"
func main() {
   //声明类型相同的多个变量, 适用于局部变量
   var a, b, c int //声明变量类型
   a, b, c = 1, 2, 3
   fmt.Println(a, b, c)
   var d, e, f = 4, 5, 6 // 不声明变量类型,自动推断
   fmt.Println(d, e, f)
   // 这种因式分解关键字的写法一般用于声明全局变量
   var (
      g bool
      h int
   )
   fmt.Println(g, h)
}

输出结果:

1 2 3

4 5 6

false 0

四、 Go的语言常量

常量是一个简单值的标识符,在程序运行时,不会被修改的量。

常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

常量的定义格式(一般可以省略type,因为编译器会自动推断常量类型):

const name [type] = value

多个相同类型的声明可以简写为:

const a, b = value1, value2
实例展示:
package main
import "fmt"
func main() {
   const LENGTH int = 10
   const WIDTH int = 5
   var area int
   area = LENGTH * WIDTH
   fmt.Printf("矩形的面积为 : %d", area)
}
输出结果:
矩形的面积为 : 50

五、理解拓展

5.1 值类型与引用类型

int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值:

图5.1.1

使用赋值符 = 将一个变量的值赋值给另一个变量时,如:j = i,实际上是在内存中将 i 的值进行了拷贝:

图5.1.2

我们可以通过 &i 来获取变量 i 的内存地址,例如:0xf840000040(每次的地址都可能不一样)。

值类型变量的值存储在堆中。

一个引用类型的变量 r1 存储的是 r1 的值所在的内存地址(数字),或内存地址中第一个字所在的位置。

图5.1.3

这个内存地址称之为指针,这个指针实际上也被存在另外的某一个值中。 同一个引用类型的指针指向的多个字可以是在连续的内存地址中(内存布局是连续的),这也是计算效率最高的一种存储形式;也可以将这些字分散存放在内存中,每个字都指示了下一个字所在的内存地址。

当使用赋值语句 r2 = r1 时,只有引用(地址)被复制。

如果 r1 的值被改变了,那么这个值的所有引用都会指向被修改后的内容,在这个例子中,r2 也会受到影响。

5.2 变量拓展

在相同的代码块中,我们不可以再次对于相同名称的变量使用初始化声明,例如:a := 20 就是不被允许的,编译器会提示错误 no new variables on left side of :=,但是 a = 20 是可以的,因为这是给相同的变量**赋予一个新的值。

如果在定义变量 a 之前使用它,则会得到编译错误 undefined: a

如果声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误 a declared but not used

空白标识符 _ 也被用于抛弃值,如值 5 在:_, b = 5, 7 中被抛弃。 _ 实际上是一个只写变量,不能得到它的值。这样做是因为 Go 语言中必须使用所有被声明的变量,但有时并不需要使用从一个函数得到的所有返回值。

实例展示:
package main
import "fmt"
func main() {
   _, numb, strs := numbers() //只获取函数返回值的后两个
   fmt.Println(numb, strs)
}
//一个可以返回多个值的函数
func numbers() (int, int, string) {
   a, b, c := 1, 2, "str"
   return a, b, c
}

输出结果: 2 str

5.3 常量拓展

  • 常量还可以用作枚举,如果定义常量组时,如果不提供初始值,则表示将使用上行的表达式。
实例展示:
package main
import "fmt"
const (
   a = 1
   b
   c
)
func main() {
   fmt.Println(a, b, c)
}

输出结果: 1 1 1 iota,特殊常量,可以认为是一个可以被编译器修改的常量。

  • iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。 iota 也可以被用作枚举值
实例展示:
package main
import "fmt"
func main() {
   const (
      a = iota    //0
      b           //1
      c           //2
      d = "Hello" //iota += 1
      e           //   iota += 1
      f = 100     //iota +=1
      g           //  iota +=1
      h = iota    //7,恢复计数
      i           //8
   )
   fmt.Println(a, b, c, d, e, f, g, h, i)
}

输出结果: 0 1 2 Hello Hello 100 100 7 8

**笔者有话说:虽然刚开始接触一门全新的语言,一切都是那么的陌生,但是只要我们不断的学习和复习,不断的总结,不断的实践,相信,掌握很快就会这门语言!