Go语言学习笔记

Hello world

1
2
3
4
5
6
package main
import "fmt"

func main() {
fmt.Println("hello")
}
  • package main表示一个可独立执行的程序,main函数必须写在main包里,每个 Go 应用程序都包含一个名为 main 的包
  • {不能换行
  • 输入go run hello.go运行,go build hello.go编译

基础语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// 当前程序的包名
package main

// 导入其他包
import "fmt"
import . "fmt" // 类似于python的import * from
// 同时导入多个
import (
"fmt"
"math"
)

// 常量定义
const PI = 3.14
// 可以用作枚举类型
const (
Unknown = 0
Female = 1
Male = 2
)
const (
a = iota // 0
b = iota // 1
c = iota // 2
)

// 全局变量的声明和赋值
var name = "go"

var flag bool // 声明
var flag = false // 声明+初始化
flag := false // (等价于↑)简短声明


// 一般类型声明
type newType int

// 结构的声明
type user struct{}

// 接口的声明
type golang interface{}

// 函数名首字母小写即为 private;大写表示public,可以被外部包调用
func getId() int {}
func Printf() {}

//可以返回多个值
func numbers()(int,int,string){
a , b , c := 1 , 2 , "str"
return a,b,c
}

// for 循环 (没有while关键字)
for i := 0; i < 100; i++ {
}
for true {
}

// 数组
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
balance :=[...]float32{1.0,2.0,3.0} // ... 可省略
len(balance) // 长度
numbers := make([]int,0,5) // (类型,len,cap)
// 追加元素
balance = append(balance, 5, 6, 6, 7)

// 切片,容量不会改变
s := []int{2, 3, 5, 7, 11, 13} // len=6 cap=6 [2 3 5 7 11 13]
s = s[:0] // len=0 cap=6 []
s = s[:2] // len=2 cap=6 [2 3]

// range 遍历
for i, num := range nums {
if num == 3 {
fmt.Println("index:", i)
}
}

// map
/* 声明变量,默认 map 是 nil,若不初始化,不能插入 */
var map_variable map[key_data_type]value_data_type
/* 或 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)

OOP

Go没用类,但可以给struct定义方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type Student struct {
id int
name string
grade1 float32
grade2 float32
}

// 接收者↓
func (s Student) getAvg() float32 {
return (s.grade1 + s.grade2) / 2.0
}
// 指针接收者↓(可以修改成员变量的值)
func (s *Student) setName(name string){
s.name=name
}

func structTest() {
s1 := Student{id: 10, grade1: 85}
s1.grade2 = 90
s1.setName("AA")
fmt.Println(s1)
fmt.Println("avg", s1.getAvg())
}

接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// interface
type People interface {
GetName() string
}

type Student struct {
name string
age int
}
// 指针接收者
func (s *Student) GetName() string {
return s.name
}

type Teacher struct {
name string
age int
}

// 值接收者
func (t Teacher) GetName() string {
return t.name
}

func interfaceTest() {
var p1 People
t := Teacher{name: "t1"}
s := Student{name: "s1"}

p1 = t // Teacher 实现了 GetName()
p1.GetName()
p1 = &t // *Teacher 的实体实现了GetName()
p1.GetName() // 实际(*p1).GetName()

//p1 = s // 错误:Student 没有实现GetName()方法
p1 = &s // *Student 实现了GetName()方法
p1.GetName()
}

总结:实现了值接收者的方法,相当于自动实现了指针接收者的方法;而实现了指针接收者的方法,不会自动生成对应值接收者的方法。

类型断言

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var i interface{} = "hello"
// t := i.(T) // 访问接口i底层的具体值,只有接口能调用该方法
s := i.(string)
fmt.Println(s)

// 可返回两个值,第二个值表示是否成功(不会报错)
s, ok := i.(string)
fmt.Println(s, ok)
// hello true

f, ok := i.(float64)
fmt.Println(f, ok)
// 0 false

f = i.(float64) // 报错 panic: interface conversion: interface {} is string, not float64
fmt.Println(f)

类型选择

可以用switch语句进行类型判断

1
2
3
4
5
6
7
8
switch v := i.(type) {
case T:
// v 的类型为 T
case S:
// v 的类型为 S
default:
// 没有匹配,v 与 i 的类型相同
}
作者

江风引雨

发布于

2021-08-18

更新于

2024-07-10

许可协议

CC BY 4.0

评论