发布于 

go语言入门

go语言入门 | 笔记整理!

基础部分

变量

1
2
3
4
5
6
7
8
9
10
11
12
13
// 变量赋值手法
func test() {
// 1.定义
var name string
name = "yasuo"
// 2.定义时直接复制
var city = "yasuo"
// 3.自动推导
ans := 100
// 4.平行复制
i, j := 10, 20
fmt.Println("变量赋值手法! ", name, city, ans, i, j)
}

自增自检

1
2
3
4
5
6
7
8
// 自增 自减 (必须单独一行)不支持三目运算符
func test02() {
i := 20
i++
fmt.Println("i:", i)
i--
fmt.Println("i:", i)
}

指针

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
// 可以返回栈上的指针
func testPtr() *string {
name := "yasuo"
return &name
}
func main() {
test()
test02()

// 指针部分 (垃圾回收机制 开发人员不是过分需要手动释放内存
// go支持返回栈上指针 (内存逃逸
// 指针为空nil

// 1.直接分配
name := "yasuo"
ptr := &name
fmt.Println("name", ptr, *ptr)
// 2.new进行分配
namePtr := new(string)
*namePtr = "yasuo"
fmt.Println("name", namePtr, *namePtr)
// 3.栈上指针 返回 (编译器会进行操作的
ans := testPtr()
if ans == nil {
fmt.Println("指针为空")
}
fmt.Println("栈上指针:", ans, *ans)
}

不支持的操作

  1. 不支持++i,--i

  2. 不支持地址加减

  3. 不支持三目运算符

  4. 只有false才能代表代码逻辑为,数字0nil不支持

字符串

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
// 字符串
func test3() {

// 1. 直接使用
name := "name"

// 2. 需要换行时候
usage := `./a.out
./help
./play
`
fmt.Println(name, usage)

// 3.长度和访问 没有length方法 有自由函数 len()
l := len(name)
fmt.Println(l)

// 4.格式化输出
for i := 0; i < len(name); i++ {
fmt.Printf("i:%d,v%c\n", i, name[i])
}

// 5.字符串拼接
i, j := "libai", "hanxin"
fmt.Println("i+j:", i+j)

// 6.字符串比较
fmt.Println("i>j:", i > j)
}

数组+ 切片

数组

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
// 数组
func test04() {
// 1.直接使用
var nums = [10]int{1, 2, 3}
num := [10]int{1, 2, 3}
fmt.Println(nums, num)

// 2. 不定长数组 使用make处理
// 换种说法 为slice
names := []string{"北京", "上海", "安徽", "四川"}
for k, v := range names {
fmt.Println(k, v)
}
// 2.1 数组追加
// 注意: 不仅是有长度的概念 也是有容量的概念
// 会根据使用情况 + 2*现在长度内存
names1 := append(names, "西安")
names1 = append(names1, "西藏")
fmt.Println(names, len(names), cap(names), "\n", names1, len(names1), cap(names1))
// 遍历处理方式
for i := 0; i < len(nums); i++ {
fmt.Print(i, nums[i], "\t")
}
fmt.Println()
// 注意:修改v不会概念nums的值 nums[i]修改才会更改的!
// 对于k,v只会存储一次 不断的进行重复赋值
for k, v := range nums {
fmt.Print(k, v, "\t")
}

// 注意:如果想要忽略某一个值 可以用 _ 来占位忽略
}

切片

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
// 切片
func test05() {
names := [7]string{"yasuo", "libai", "hanxin", "zhangfei", "liubei", "liubei"}

names1 := [3]string{}
names1[0] = names[0]
names1[1] = names[1]
names1[2] = names[2]

fmt.Println(names1)

// 切片选择就跟python用法差不多一致
// 但只是浅拷贝
names2 := names[0:3]
names2[0] = "wuzetian"
fmt.Println(names2, names)

// 必须数据污染 可以进行 copy
arr := make([]string, len(names))
copy(arr, names[:])
fmt.Println("copy后的arr", arr)

// 可以对于字符串进行切片截取: 取字符串的子串
he := "hello world"
fmt.Println("sub", he[5:8])

// 创建空切片 可以指定一下容量
ls := make([]int, 0, 20)
fmt.Println(ls, len(ls), cap(ls))
}

字典

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
// 字典
func test06() {
// 存储的是 key:value的映射关系

// 1.基础使用
// 需要分配内存 不然会出现
// panic: assignment to entry in nil map
var idNames map[int]string

// 2. 分配空间 可以分配长度
idNames = make(map[int]string)
// 3.可以直接 赋值推导
// idNames := make(map[int]string)
idNames[0] = "yasuo"
idNames[1] = "hanxin"

// 4.遍历map
for k, v := range idNames {
fmt.Println(k, v)
}

// 判断key存在于map 不存在的话 会返回一个nil
// 可以借助 第二个参数接受状态
name3, err := idNames[3]
fmt.Println(name3, err)

// 5.删除数值
// 通过自由函数 delete删除制定的key
fmt.Println(idNames)
delete(idNames, 1)
delete(idNames, 100) // 删除不存在的不会报错
fmt.Println(idNames)
}

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 函数返回值 在参数列表之后
// 如果有多个返回值 需要使用括号 进行包裹
// 多个参数使用 , 分割
func test(a int, b int, c string) (int, string, bool) {
return a * b, c, true
}

// 类型相同的话 可以连着一起操作
// 当返回值 有名字的时候 可以直接简写return
func test1(a, b int, c string) (res int, str string, bl bool) {
res = a * b
str = c
bl = true
return
}

// 当返回值 只有一个参数 并且没有名字 不需要加圆括号
func test2() int {
return 10
}

内存逃逸

1
2
3
4
5
6
7
8
9
10
func testptr() *string {

name := "yasuo"
p0 := &name
fmt.Println("*po", *p0)

city := "xicdan"
ptr := &city
return ptr
}

查看方法

1
go build -gcflags="-m -m -l" 内存逃逸.go >1.txt 2>&1

相关笔记

[Go] 详解内存逃逸 - 掘金

import

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 如果函数是想被外部访问时候 函数开头要大写 相当于public
// 内部是完全可以使用的

package main

import (
"awesomeProject/src/add"
//"awesomeProject/src/sub" // 常规导入模式
//SUB "awesomeProject/src/sub" //类似于重命名
. "awesomeProject/src/sub" //导入所有包
"fmt"
)

func main() {
res := Sub(20, 10)
fmt.Println("res:", res)

ret := add.Add(20, 20)
fmt.Println("ret:", ret)
}
1
2
3
4
5
package sub

func Sub(a, b int) int {
return a - b
}
1
2
3
4
5
package add

func Add(a, b int) int {
return a + b
}

目录形式

1
2
3
4
5
6
7
文件夹 PATH 列表
卷序列号为 4829-01C8
C:.
├─.idea
└─src
├─add
└─sub

GOLANG导入自己写的 包/函数_go引入自己的包_江枫霜的博客-CSDN博客

switch + os

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

import (
"fmt"
"os"
)

func main() {

// 命令行输入
// c:argc,**argv
// go:os.Args -->build一下 命令行执行
cmds := os.Args
//for k, v := range cmds {
// fmt.Println("key", k, "value", v, "len", len(cmds))
//}
if len(cmds) < 2 {
fmt.Println("please input the arguments")
return
}
switch cmds[1] {
case "hello":
fmt.Println("hello world")
fallthrough // 向下穿透
case "world":
fmt.Println("world hello")
default:
fmt.Println("hello yasuo")
}
}

条件控制语句

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"

func main() {
// 标签 label1
// goto label1 下一次进入循环时候 i不会保存之前的状态 重新从0开始
// break label1 直接跳出当前循环
// continue label1 下一下进入循环时候 会记录之前的状态
label:
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
if j == 3 {
//goto label
//continue label
break label
}
fmt.Println("i:", i, "j:", j)
}
}
fmt.Println("over")
}

枚举

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

import "fmt"

// 模拟表示一周
const (
Monday = iota
Tuesday
Wendesday
Thursday
Friday
Saturday
Sunday
is_7, not_7 = iota, iota
)

func main() {
// go语言没有枚举类型 可以使用const + iota(常量累加器)模拟实现
// 每换行一次+1 (同一行的iota的数值都是一样的
// 不赋值的话 默认与上一行表达式一致
// 每一个iota是独立的 遇到const iota会重新清零

// 很多定义时候
//var num int
//var name string
//var flag bool
// 使用变量组来统一定义
//var(
// num int
// name string
// flag bool
//)
fmt.Println(Monday, Tuesday, Wendesday, Thursday, Friday, Saturday, Sunday)
fmt.Println(is_7, not_7)
}

结构体

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

import "fmt"

// c语言 重名 typedef int myInt
type myInt int

// Person go 语言结构体 type + struct
type Person struct {
name string
age int
gender string
score float64
}

func main() {
var i, j myInt
i, j = 10, 20
fmt.Println("i+j:", i+j)

// 完全赋值的话 字段名可以不写
yasuo := Person{"yasuo", 18, "male", 61}
//yasuo := Person{
// name: "yasuo",
// age: 18,
// gender: "male",
// score: 61,
//}

// 打印输出方式
fmt.Println(yasuo)
ptr1 := &yasuo
fmt.Println((*ptr1).name, (*ptr1).age, (*ptr1).gender, (*ptr1).score)
fmt.Println(yasuo.name, yasuo.age, yasuo.gender, yasuo.score)

// 如果不完全赋值的话 必须指定变量名字
yongen := Person{
name: "yongen",
age: 64,
}
//yongen := Person{"yongen", 64} // 会报错
fmt.Println(yongen)
}

init初始化

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

import "fmt"

// 1. init初始化函数 没有参数 没有返回值
// 2. 一个包含多个init时 调用顺序不确定
// 3. init函数是不允许用户显示调用的
// 4. 有的时候引用一个包 可能只想使用这个包的 init函数的话 (例如mysql的初始化)
// 不想使用其他函数 为了防止编译器报错 可以使用_来处理
func init() {
fmt.Println("this is init() in package sub")
}
func init() {
fmt.Println("this is second init() in package sub")
}
func Sub(a, b int) int {
return a - b
}
1
2
3
4
5
6
7
8
9
10
package main

import (
_ "init/sub" // 不想使用其他函数 只想使用init 为了防止编译器报错 可以使用_来处理
)

func main() {
//res := sub.Sub(20, 10)
//fmt.Println("sub.Sub(20,10)", res)
}

defer

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

import (
"fmt"
"os"
)

func readFile(filename string) {
fl, err := os.Open(filename)
// 这样来写用到了 defer
//defer fl.Close()
// 也可以使用 匿名函数关闭文件
defer func() {
fmt.Println("will close file")
_ = fl.Close()
}()
if err != nil {
fmt.Println("file to open file:", filename)
return
}
buf := make([]byte, 1024)
n, _ := fl.Read(buf)
fmt.Println("len:", n, "info:", string(buf))

defer fmt.Println("next defer statement")
defer fmt.Println("last defer statement")
}
func main() {
// 1. defer 延迟 关键字 用来修饰关键字 函数 在退出时候 一定会执行
// 2. 一般用于资源清理
// 3. 解锁和关闭文件
// 4. 在同一个函数中 多次调用defer 执行时 类似于stack
// 多次defer语句 最后写的defer 先执行 stack特征
filename := "base_go1/defer/test.txt"
readFile(filename)
}