Golang基础学习

Go 语言教程 | 菜鸟教程 (it028.com)

goland开发环境搭建及运行第一个go程序HelloWorld_goland helloworld-CSDN博客

基础语法

Go 语言教程 | 菜鸟教程 (it028.com)

语句后不需要;

{不能单独一列

switch

注意switch支持多值匹配:

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() {
day := "Thursday"

switch day {
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
fmt.Println(day, "is a weekday.")
case "Saturday", "Sunday":
fmt.Println(day, "is a weekend.")
default:
fmt.Println(day, "is not a valid day.")
}
}

fallthrough关键字强制执行下一个case的内容,switch不需要break(但java需要)

注意if和switch没有()的使用

函数定义:

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

import "fmt"

func add(a int, b int) int { //返回值类型在后面
var result int
result = a + b
return result
}

func main() {
a := 2
b := 3
ans := add(a, b)
fmt.Printf("ans is %d", ans)
}
//如果有多个返回值
func addAndMutiply(a,b int)(int,int){
var result1 int
var result2 int
result1 = a+b
result2 = a*b
return result1,result
}

数组:

1
2
3
var nums[5] int
var nums = [5]int{0,1,2,3,4}
var nums = []int{1,3,5,7,9,10}

获取数组长度:

image-20240921100411946.png

指针:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var a int
var ptr *int
ptr = &a
fmt.Printf("the num is %d\n",a)
fmt.Printf("the address of a is %x\n",&a)
fmt.Printf("the address is %x\n",ptr)
fmt.Printf("the num of the address is %d\n",*ptr)

//空指针
var nullPtr *int
fmt.Printf("nullPtr的值为%x",nullPtr) //输出为0

//判断是否为空指针
if (nullPtr==nil)

结构体和结构体指针:

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

import "fmt"

type Books struct {
title string
author string
subject string
book_id int
}

func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
var Book2 Books /* 声明 Book2 为 Books 类型 */

/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407

/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6495700

/* 打印 Book1 信息 */
fmt.Printf( "Book 1 title : %s\n", Book1.title)
fmt.Printf( "Book 1 author : %s\n", Book1.author)
fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)

/* 打印 Book2 信息 */
fmt.Printf( "Book 2 title : %s\n", Book2.title)
fmt.Printf( "Book 2 author : %s\n", Book2.author)
fmt.Printf( "Book 2 subject : %s\n", Book2.subject)
fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)
}
//结构体指针
package main

import "fmt"

type Books struct {
title string
author string
subject string
book_id int
}

func main() {
var Book1 Books /* Declare Book1 of type Book */
var Book2 Books /* Declare Book2 of type Book */

/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407

/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6495700

/* 打印 Book1 信息 */
printBook(&Book1)

/* 打印 Book2 信息 */
printBook(&Book2)
}
func printBook( book *Books ) {
fmt.Printf( "Book title : %s\n", book.title)
fmt.Printf( "Book author : %s\n", book.author)
fmt.Printf( "Book subject : %s\n", book.subject)
fmt.Printf( "Book book_id : %d\n", book.book_id)
}

切片:

1
2
3
4
5
6
7
8
9
10
len:=3
cap:=5
var nums[] int = make([]int,len)
var nums2[] int = make([]int,len,cap) //length,capacity

//切片初始化
var arr[] int = []int{5,6,7,1,2}
var s[] int = arr[:] //cap=len=5
s2[] = arr[0:5] //startIndex = 0,endIndex = 5-1=4

完整的切片例子:

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

import "fmt"

func main() {
/* 创建切片 */
numbers := []int{0,1,2,3,4,5,6,7,8}
printSlice(numbers)

/* 打印原始切片 */
fmt.Println("numbers ==", numbers)

/* 打印子切片从索引1(包含) 到索引4(不包含)*/
fmt.Println("numbers[1:4] ==", numbers[1:4])

/* 默认下限为 0*/
fmt.Println("numbers[:3] ==", numbers[:3])

/* 默认上限为 len(s)*/
fmt.Println("numbers[4:] ==", numbers[4:])

numbers1 := make([]int,0,5)
printSlice(numbers1)

/* 打印子切片从索引 0(包含) 到索引 2(不包含) */
number2 := numbers[:2]
printSlice(number2)

/* 打印子切片从索引 2(包含) 到索引 5(不包含) */
number3 := numbers[2:5]
printSlice(number3)

}

func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

切片的append和copy

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

import "fmt"

func main() {
var numbers []int
printSlice(numbers)

/* 允许追加空切片 */
numbers = append(numbers, 0)
printSlice(numbers)

/* 向切片添加一个元素 */
numbers = append(numbers, 1)
printSlice(numbers)

/* 同时添加多个元素 */
numbers = append(numbers, 2,3,4)
printSlice(numbers)

/* 创建切片 numbers1 是之前切片的两倍容量*/
numbers1 := make([]int, len(numbers), (cap(numbers))*2)

/* 拷贝 numbers 的内容到 numbers1 */
copy(numbers1,numbers)
printSlice(numbers1)
}

func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}

range:

Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。

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
package main
import "fmt"
func main() {
//这是我们使用range去求一个slice的和。使用数组跟这个很类似
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println("sum:", sum)
//在数组上使用range将传入index和值两个变量。上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引。
for i, num := range nums {
if num == 3 {
fmt.Println("index:", i)
}
}
//range也可以用在map的键值对上。
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
//range也可以用来枚举Unicode字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
for i, c := range "go" {
fmt.Println(i, c)
}
}

结果:

1
2
3
4
5
6
sum: 9
index: 1
a -> apple
b -> banana
0 103
1 111

Map:

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

import "fmt"

func main() {
var countryCapitalMap map[string]string /*创建集合 */
countryCapitalMap = make(map[string]string)

/* map插入key - value对,各个国家对应的首都 */
countryCapitalMap [ "France" ] = "巴黎"
countryCapitalMap [ "Italy" ] = "罗马"
countryCapitalMap [ "Japan" ] = "东京"
countryCapitalMap [ "India " ] = "新德里"

/*使用键输出地图值 */
for country := range countryCapitalMap {
fmt.Println(country, "首都是", countryCapitalMap [country])
}

/*查看元素在集合中是否存在 */
capital, ok := countryCapitalMap [ "American" ] /*如果确定是真实的,则存在,否则不存在 */
/*fmt.Println(capital) */
/*fmt.Println(ok) */
if (ok) {
fmt.Println("American 的首都是", capital)
} else {
fmt.Println("American 的首都不存在")
}
}

delete函数

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

import "fmt"

func main() {
/* 创建map */
countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"}

fmt.Println("原始地图")

/* 打印地图 */
for country := range countryCapitalMap {
fmt.Println(country, "首都是", countryCapitalMap [ country ])
}

/*删除元素*/ delete(countryCapitalMap, "France")
fmt.Println("法国条目被删除")

fmt.Println("删除元素后地图")

/*打印地图*/
for country := range countryCapitalMap {
fmt.Println(country, "首都是", countryCapitalMap [ country ])
}
}
1
2
3
4
5
6
7
8
9
10
原始地图
India 首都是 New delhi
France 首都是 Paris
Italy 首都是 Rome
Japan 首都是 Tokyo
法国条目被删除
删除元素后地图
Italy 首都是 Rome
Japan 首都是 Tokyo
India 首都是 New delhi

接口

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。

接口->结构->func(结构)call(){}

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

import (
"fmt"
)

type Phone interface {
call()
}

type NokiaPhone struct {
}

func (nokiaPhone NokiaPhone) call() {
fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
}

func (iPhone IPhone) call() {
fmt.Println("I am iPhone, I can call you!")
}

func main() {
var phone Phone

phone = new(NokiaPhone)
phone.call()

phone = new(IPhone)
phone.call()

}
1
2
I am Nokia, I can call you!
I am iPhone, I can call you!

错误处理

image-20240921105246309.png

例子:

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

import (
"fmt"
)

// 定义一个 DivideError 结构
type DivideError struct {
dividee int
divider int
}

// 实现 `error` 接口
func (de *DivideError) Error() string {
strFormat := `
Cannot proceed, the divider is zero.
dividee: %d
divider: 0
`
return fmt.Sprintf(strFormat, de.dividee)
}

// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
if varDivider == 0 {
dData := DivideError{
dividee: varDividee,
divider: varDivider,
}
errorMsg = dData.Error()
return
} else {
return varDividee / varDivider, ""
}

}

func main() {

// 正常情况
if result, errorMsg := Divide(100, 10); errorMsg == "" {
fmt.Println("100/10 = ", result)
}
// 当除数为零的时候会返回错误信息
if _, errorMsg := Divide(100, 0); errorMsg != "" {
fmt.Println("errorMsg is: ", errorMsg)
}

}

并发/协程

Go 并发 | 菜鸟教程 (it028.com)

golang学习笔记(协程的基础知识)_协程 golang-CSDN博客

在Go语言中,要创建一个协程,只需在函数调用前加上关键字”go”。下面是一个简单的示例:

1
go 函数名()

这样就创建了一个新的协程,并在该协程中执行相应的函数。协程会与主线程并发执行,不会阻塞主线程的执行。

协程之间可以通过通道(Channel)进行通信。通道是一种在多个协程之间同步和传递数据的机制,它能够保证并发安全。通过通道,协程可以发送和接收数据,实现协程之间的协作。

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"
"time"
)

func longRunningTask() (res int) {
time.Sleep(time.Second)
for i := 0; i < 10; i++ {
res += i
}
return res
}

func main() {
result := make(chan int)

go func() {
result <- longRunningTask()
}()

fmt.Println("Waiting for result...")
fmt.Println("Result:", <-result)
}


make和new

[深入理解 Golang 中 New() 和 make() 的区别_golang new-CSDN博客](https://blog.csdn.net/qq_53742640/article/details/137696417?ops_request_misc=&request_id=&biz_id=102&utm_term=golang make&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-137696417.nonecase&spm=1018.2226.3001.4187)

[golang 中 new 和 make 详解_golang make new-CSDN博客](https://blog.csdn.net/u012730525/article/details/136390719?ops_request_misc=&request_id=&biz_id=102&utm_term=golang make&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-2-136390719.nonecase&spm=1018.2226.3001.4187)

包管理

Golang 基础 Go Modules包管理_golang包管理-CSDN博客

go怎么引入其他Go package文件(vscode中)_go怎么引入别的文件-CSDN博客

注意GOPATH和go.mod不能共存,用go.mod好一些

$GOPATH/go.mod exists but should not-CSDN博客