Go学习笔记

前言

Go语言相关基础知识的学习,主要参考菜鸟教程上的相关知识。

Go语言结构

Go基础组成有以下几个部分:

  • 包声明
  • 引入包
  • 函数
  • 变量
  • 语句、表达式
  • 注释
1
2
3
4
5
6
package main
import "fmt"

func main(){
fmt.Printfln("Hello,world!")
}

几点注意:

  • 一般来说启动后第一个执行的是main函数,但如果有init()函数则会先执行该函数
  • 当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 protected )
  • “{“符号不能单独放在一行
  • 文件夹名、文件名和包名没有直接关系,但同一个文件夹下的文件只能有一个包名

1
2
3
4
[Running] go run "d:\VScode\Go\project\hello\main\main.go"
# command-line-arguments
project\hello\main\main.go:5:6: missing function body
project\hello\main\main.go:6:1: syntax error: unexpected semicolon or newline before {

Go语言基础语法

行分隔符

一行即为一个语句,每个语句不需要像C一样添加”;”,这些工作由Go编译器完成。如果打算将多个语句放在同一行,则需要用;区分

关键字

保留字:

预定义标识符:

格式化字符串

Go语言使用fmt.Sprintf格式化字符串并赋值给新串,一般和Print搭配使用:

1
2
3
4
5
6
7
8
    var stockcode=123
var enddate="2020-12-31"
var url="Code=%d&endDate=%s"
var target_url=fmt.Sprintf(url,stockcode,enddate)
fmt.Println(target_url)

output:
Code=123&endDate=2020-12-31

Go语言数据类型

  • 布尔类型
  • 数字类型
  • 字符串类型
  • 派生类型
    • 指针类型(Pointer)
    • 数组类型
    • 结构化类型(struct)
    • Channel 类型
    • 函数类型
    • 切片类型
    • 接口类型(interface)
    • Map 类型

数字类型

序号 类型和描述
1 uint8 无符号 8 位整型 (0 到 255)
2 uint16 无符号 16 位整型 (0 到 65535)
3 uint32 无符号 32 位整型 (0 到 4294967295)
4 uint64 无符号 64 位整型 (0 到 18446744073709551615)
5 int8 有符号 8 位整型 (-128 到 127)
6 int16 有符号 16 位整型 (-32768 到 32767)
7 int32 有符号 32 位整型 (-2147483648 到 2147483647)
8 int64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)

浮点型

序号 类型和描述
1 float32 IEEE-754 32位浮点型数
2 float64 IEEE-754 64位浮点型数
3 complex64 32 位实数和虚数
4 complex128 64 位实数和虚数

Go语言变量

变量的声明一般用var,可以一次声明多个变量

1
var identifier1, identifier2 type

变量声明

  • 第一种,指定变量类型,如果没有初始化,则变量默认为零值。
  • 第二种,根据值自行判定变量类型。
  • 第三种,如果变量已经使用 var 声明过了,再使用 *:=* 声明变量,就产生编译错误,格式:
1
2
3
4
5
6
var intVal int 
intVal :=1 // 这时候会产生编译错误,因为 intVal 已经声明,不需要重新声明

直接使用以下语句即可:

intVal := 1 // 此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句

多变量声明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//类型相同多个变量, 非全局变量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3

var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断

vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误


// 这种因式分解关键字的写法一般用于声明全局变量
var (
vname1 v_type1
vname2 v_type2
)

注意事项

如果声明了一个局部变量却没有在相同的代码块中使用它,会得到编译错误,例如下面这个例子当中的变量 a:

1
2
3
4
5
6
7
8
package main

import "fmt"

func main() {
var a string = "abc"
fmt.Println("hello, world")
}

但是全局变量是允许声明但不使用的。

并行:

1
2
3
var a, b int
var c string
a, b, c = 5, 7, "abc" //可称为并行 或 同时 赋值
空白标识符

空白标识符 _ 也被用于抛弃值,如值 5 在:_, b = 5, 7 中被抛弃。

_ 实际上是一个只写变量,你不能得到它的值。

这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
}

Go语言常量

常量定义格式:

1
const identifier [type] = value

常量还可用于枚举

1
2
3
4
5
const (
Unknown = 0
Female = 1
Male = 2
)

iota

iota是go里面的特殊常量,可以认为是一个可以被编译器修改的常量。

iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。

iota用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import "fmt"

func main() {
const (
a = iota //0
b //1
c //2
d = "ha" //独立值,iota += 1
e //"ha" iota += 1
f = 100 //iota +=1
g //100 iota +=1
h = iota //7,恢复计数
i //8
)
fmt.Println(a,b,c,d,e,f,g,h,i)
}

//输出:0 1 2 ha ha 100 100 7 8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import "fmt"
const (
i=1<<iota
j=3<<iota
k
l
)

func main() {
fmt.Println("i=",i)
fmt.Println("j=",j)
fmt.Println("k=",k)
fmt.Println("l=",l)
}

//输出:
i= 1
j= 6
k= 12
l= 24

Go语言运算符

这部分没什么好扩充的,记录下容易忘的运算符优先级

5 * / % << >> & &^
4 + - | ^
3 == != < <= > >=
2 &&
1 ||

Go的条件语句

(1)if语句用法

1
2
3
if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
}

(2)if..else语句用法

1
2
3
4
5
if 布尔表达式 {
/* 在布尔表达式为 true 时执行 */
}else{
/* 在布尔表达式为 false 时执行 */
}

(3)if嵌套语句

1
2
3
4
5
6
if 布尔表达式1{
/* 在布尔表达式 1 为 true 时执行 */
if 布尔表达式2{
/* 在布尔表达式 2 为 true 时执行 */
}
}

(4)switch语句

1
2
3
4
5
6
7
8
switch var1 {
case val1:
...
case val2:
...
default:
...
}

需要注意的是:

  • 支持多条件匹配
  • 不同的 case 之间不使用 break 分隔,默认只会执行一个 case
  • 如果想要执行多个 case,需要使用 fallthrough 关键字,也可用 break 终止
1
2
3
4
5
6
7
8
9
10
11
12
13
switch{
case 1:
...
if(...){
break
}

fallthrough // 此时switch(1)会执行case1和case2,但是如果满足if条件,则只执行case1

case 2:
...
case 3:
}

(5)select语句