Golang

概述

Go的优势

  1. 极其简单的部署方式
    1. 可以直接编译成机器码
    2. 不依赖其他库
    3. 可直接运行即可部署
  2. 静态语言
    1. 编译的时候检查出来大多数问题
  3. 语言层面的并发
    1. 天生基因支持,
    2. 充分的运用多核
  4. 强大的标准库
    1. runtime系统调度机制
    2. 高效的GC垃圾回收
    3. 丰富的标准库
  5. 简单易学
    1. 25个关键字
    2. 支持内嵌C语言
    3. 面向对象语言
    4. 跨平台

HelloGolang

go的语法是和python比较像的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main //当前程序的包名
//可以这样导包
import (
"fmt"
"time"
)

// main函数
func main() { //函数的大{一定与函数名是在一行的,不然报错
//打印语句
fmt.Print("hello go")
//不用分号
time.Sleep(1 * time.Second)
}

golang变量声明的四种方式

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
package main

import "fmt"

/*
声明变量的四种方式
*/

func main() {
//方法一:声明一个变量,默认值是0
var a int
fmt.Println("a=", a)
fmt.Printf("type of a= %T\n", a)
//方法二:添加一个默认值
var b int = 100
fmt.Println("b=", b)
fmt.Printf("type of b= %T\n", b)
//方法三,在初始化时,不添加数据类型,通过值自动匹配当前数据类型
var c = 100
fmt.Println("c=", c)
fmt.Printf("type of c= %T\n", c)
//方法四:(常用方法)省去var关键字,直接自动匹配

d := 200
fmt.Println("d=", d)
fmt.Printf("type of d = %T\n", d)
}

在声明全局变量时,我们使用上述的四种方法发现image-20240307153550814

编译直接报错image-20240307153624942

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	//声明多个变量

//相同数据类型
var aa ,bb ="123","456"
fmt.Printf(aa,bb)
//不同数据类型
var cc ,dd=123,"123"
fmt.Println(cc,dd)

//多行的多变量声明
var (
vv int =100
xx bool =true
)
fmt.Println(vv,xx)

常量与枚举

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

import "fmt"

// const可以用来定义枚举
const (
//可以在const()中加入关键字iota,每行iota都会累计+1,第一行的iota默认是0
SHANGHAI = iota
NANJING
CHONGQING
)

func main() {
//常量只读不可修改
const length int = 100
fmt.Println(length)
fmt.Println(SHANGHAI)
fmt.Println(NANJING)
fmt.Println(CHONGQING)
}

image-20240307155759355

golang函数的参数与返回结果

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

import "fmt"

func fool(i int, b string) int {
fmt.Println(i)
fmt.Println(b)
c := 100
return c
}

func main() {
var c = fool(1, "zf")
fmt.Println("the result is=", c)
}

也可有多个返回结果

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

import "fmt"

func fool(i int, b string) (int, int) {
fmt.Println(i)
fmt.Println(b)
c := 100
d := 200
return c, d
}

func main() {
var c, d = fool(1, "zf")
fmt.Println("the result is=", c)
fmt.Println("the result is=", d)
}

image-20240307164319581

在import本项目包时,会先去调用.go文件中的init方法,倘若导包后没有使用该包的函数,也会去执行init方法,且包中的对外的函数必须函数名首字母大写

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
---------lib1---------
package lib1

import "fmt"

//注意方法名首字母大写
func Lib1Test() {
fmt.Println("lib1Test-----")
}

func init() {
fmt.Println("lib1-----init")
}
-------lib2--------
package lib2

import "fmt"

func Lib2Test() {
fmt.Println("lib2Test-----")
}
//注意方法名首字母大写
func init() {
fmt.Println("lib2---init")
}

在调用时

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

import (
"golnagCode/lib1"
"golnagCode/lib2"
)
/*
import(
_"golangCode/lib1" 先导入但暂时不使用该包
. ”golangCOde/lib2“ 将该包中的函数在本文件中作为静态函数可直接调用而不用 包名.函数名
myfunc ”golangCode/lib1“ 给该包起别名,别名为myfunc
)
*/

func main() {
lib1.Lib1Test()
lib2.Lib2Test()
}

执行结果image-20240307172646372

defer

在函数中,程序员经常需要创建资源(比如:数据库连接、文件句柄、锁等),为了在函数执行完毕后,及时的释放资源,Go的设计者提供defer (延时机制)

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

import "fmt"

func func1() {
fmt.Println("A")
}

func func2() {
fmt.Println("B")
}
func func3() {
fmt.Println("C")
}

func main() {
defer func1()
defer func2()
defer func3()

输出结果

image-20240307212209142

数组与动态数组

1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
myarray := [10]int{1, 2, 3, 4}
//for i := 0; i < len(myarray); i++ {
// fmt.Println(myarray[i])
//}

for index, value := range myarray {
fmt.Println("index=", index, ",value=", value)
}

fmt.Printf("myarray type of %T\n", myarray)
}

image-20240310181139452

slice切片

切片(slice)是对数组的一个连续片段的引用,所以切片是一个引用类型,这个片段可以是整个数组,也可以是由起始和终止索引标识的一些项的子集,需要注意的是,终止索引标识的项不包括在切片内。

Go语言中切片的内部结构包含地址、大小和容量,切片一般用于快速地操作一块数据集合,如果将数据集合比作切糕的话,切片就是你要的“那一块”,切的过程包含从哪里开始(切片的起始位置)及切多大(切片的大小),容量可以理解为装切片的口袋大小,如下图所示
image-20240310193111677

示例:

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

func main() {
// 创建一个切片
slice := []int{1, 2, 3, 4, 5}
slice2 := slice[1:3]
for i, v := range slice2 {
fmt.Printf("索引为:%d,值为:%d\n", i, v)
}
}

image-20240310201554630

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

import "fmt"

func main() {
slice := []int{1, 2, 3, 4}
slice2 := make([]int, len(slice))
fmt.Println("--容量为:", cap(slice2))
slice2 = slice[1:3]
for i, v := range slice2 {
fmt.Println("索引为:", i, "值为:", v)
}
fmt.Println("----------------")
slice2 = append(slice2, 1)
for i, v := range slice2 {
fmt.Println("索引为:", i, "值为:", v)
}
}

image-20240310204227142

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() {
//第一种创建方式
Mymap1 := make(map[string]string, 10)
Mymap1["1"] = "java"
Mymap1["2"] = "golang"
Mymap1["3"] = "c++"

fmt.Printf("%v\n", Mymap1)
//第二种创建方式
Mymap2 := map[int]string{
1: "2",
2: "2",
3: "2",
}
fmt.Printf("%v\n", Mymap2)
}

image-20240310211118916

对象

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
package Hero

import "fmt"

// Hero 类
type Hero struct {
Name string
age int // 小写字母开头的字段是私有的,外部包无法直接访问
level int // 同上
}

// GetName 方法
func (h *Hero) GetName() {
fmt.Println("Name =", h.Name)
}

// SetName 方法
func (h *Hero) SetName(name string) {
h.Name = name
}

// Show 方法
func (h *Hero) Show() {
fmt.Println("Name =", h.Name)
fmt.Println("Age =", h.age)
fmt.Println("Level =", h.level)
}

要谨记Java与go之间的区别,Java的方法中形参的传递方式一般使用的是值引用,而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
package main

import (
"fmt"
"strconv"
)

type Human struct {
name string
age int
height float32
}

func (h *Human) setName(a string) {
h.name = a
}

func (h *Human) say() {
fmt.Println("Now I am saying")
}

func (h *Human) show() {
fmt.Printf("name:" + h.name)
fmt.Printf("age:" + strconv.Itoa(h.age))
fmt.Printf("height:" + strconv.FormatFloat(float64(h.height), 'f', 2, 32))
}

type SuperMan struct {
*Human //继承自Human类且使用值引用,在创建human对象的同时再创建SuperMan对象 当修改human的值的话SuperMan中的值会变,结果如下图
level int
}

func (s *SuperMan) Fly() {
fmt.Println("I am SuperMan,I can fly")
}
func (s *SuperMan) show() {
fmt.Printf("name:" + s.name)
fmt.Printf(",age:" + strconv.Itoa(s.age))
fmt.Printf(",height:" + strconv.FormatFloat(float64(s.height), 'f', 2, 32))
fmt.Printf(",level:" + strconv.Itoa(s.level))
}

func main() {
human := Human{name: "zhangsan", age: 22, height: 1.75}
human.setName("lisi")
human.say()
human.show()
fmt.Println("====================")

s := SuperMan{&human, 100}
s.Fly()
s.show()
human.setName("123321")
fmt.Println()
s.show()
}

image-20240322022421787