Go Basics
所有的最开始:y分钟学会GO (opens new window)
首先我们了解GO语言,就从Go语言的整个程序结构开始了解。这也被称之为GO语言的语法。
# Go语言程序是如何运行的?
Go语言的运行编译过程跟其他语言有很大的相似性,编译的过程整体上来说,就是根据我们自己编写的源代码去生成最终的可执行文件,里面涉及到一些词法分析,语法分析相关的内容。
首先我们将这个源码进行语法分析、词法分析,然后对代码进行类型检查。这一步很多我们电脑的开发工具也能够帮我们做到(Goland)。进行完词法分析,语法分析类型检查之后,生成中间代码,然后根据中间代码生成机器代码,生成的机器代码对已有的一些运行时库或者是c语言的库进行链接,链接完成了之后就拼成了我们最终的可执行代码。
- go build :生成的可执行文件会在文件系统中,需要再手动运行一遍。
- go run :生成的可执行文件在内存中,它并不会在文件系统中生成可执行文件。
对于go语言来说,编译出一个可执行代码是有点复杂的过程,如果说我们程序所需要的c语言库在windows和在Linux上面是不一样的话,那我们整个编译过程就需要在不同的平台上完成。这种情况是不支持跨平台编译的。
# Go程序可以放在一行里写
Go语言跟其他的不一样,它不用区分第1行,第2行它可以直接将整个程序compact到同一行也可以运行。
使用 var 关键字可以声明变量,会被赋予其类型的零值 如果你声明了一个变量但没有使用它,Go编译器将会报错。这可以通过下划线 _ 来忽略某个值的方式来解决,表示我们有意不使用这个变量。
# 条件语句
If else很简单,就是一层一层的往下,不停的判断,不停的往下走。就是与非逻辑。
fallsthrough 关键字会导致 switch 语句从当前 case 分支直接执行下一个 case 分支,而不会判断下一个 case 分支的表达式是否为 true。
当switch中的语句小于三个的时候,编译器会自动把这个程序转化成if else的结构,当这个语句case大于三个的时候,在编译器里面会生成一个跳表来实现跳转逻辑。
跳表的原理就是将点分成多个层级,然后不同层级均匀分布着这些点,也就是最低的一层存储的所有的节点,每往上一层是当前层数的一半,理想的层数就是logN。
# function
package main
func f(in) (out) {
}
2
3
4
# 数据结构
# 字符串
字符串是不可变字节序列,其本身是一个复合结构。
type stringStruct struct {
str unsafe.Pointer
len int
}
2
3
4
- 它的编码是
utf-8
,不以null结尾,默认值是空字符串(""
) - 可以使用索引访问字节数组,不能获取元素的地址。
- 通过切片取得的子串,依旧指向原来的数组。
- 只内置了一个函数,len返回字节数组的长度。
通过切片取得的子串,依旧指向原来的数组:
func main() {
s := "pty1111"
s2 := s[:3]
p1 := (*reflect.StringHeader)(unsafe.Pointer(&s))
p2 := (*reflect.StringHeader)(unsafe.Pointer(&s2))
fmt.Printf("%#v, %#v\n", p1, p2)
}
// &reflect.StringHeader{Data:0xf4f7c7, Len:7}, &reflect.StringHeader{Data:0xf4f7c7, Len:3}
2
3
4
5
6
7
8
9
10
# GO:找到任意字符并打印
package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
)
func main() {
processLogFile("C:\\Users\\willo\\OneDrive\\桌面\\sn.txt", "C:\\Users\\willo\\OneDrive\\桌面\\sn_new.txt")
}
// processLogFile 处理txt文件,取出文件的每一行处理一次
func processLogFile(filePath string, newFilePath string) {
// 打开文件
file, err := os.Open(filePath)
if err != nil {
log.Fatal(err)
}
defer file.Close()
// 1.创建输出文件
_ = os.Remove(newFilePath)
outputFile, err := os.Create(newFilePath)
if err != nil {
log.Fatal(err)
}
defer outputFile.Close()
writer := bufio.NewWriter(outputFile)
// 2.创建文件读取器
scanner := bufio.NewScanner(file)
scanner.Buffer(make([]byte, 0, 1024*2024), bufio.MaxScanTokenSize*10)
// 逐行读取文件内容
for scanner.Scan() {
line := scanner.Text()
// 检查是否包含指定文本
if !strings.Contains(line, "target_content") {
// 打印匹配的行
fmt.Println(line)
}
// 回写文件
if _, err := writer.WriteString(line + "\n"); err != nil {
log.Fatal(err)
}
}
}
/**
* 拷贝文件
*/
func copyFile(src, dest string) error {
// 确保目标目录存在,不存在则创建
destDir := filepath.Dir(dest)
if err := os.MkdirAll(destDir, os.ModePerm); err != nil {
return err
}
sourceFile, err := os.Open(src)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(dest)
if err != nil {
return err
}
defer destFile.Close()
_, err = io.Copy(destFile, sourceFile)
if err != nil {
return err
}
return nil
}
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