Golang是一种开源的编程语言,由 Google 的 Robert Griesemer、Rob Pike 和 Ken Thompson 在 2007 年设计并实现。Go 语言以其简洁、高效和并发支持而闻名,它结合了编译语言的性能和解释型语言的开发效率,感觉上是简化版C语言,高效版Python。
1.基本语法
1.1变量
var<变量的声明> a<变量名> int<数据类型>=<值>
值得注意的一点是,go语言中没有字符类型,即比较常见的char,go语言中一般是Unicode编码存储字符,对于abcd等单个的字符,可以使用byte数据类型转为ASCII码进行存储。
自动判断变量类型
a := <值>
const//声明常量
根据上下文自动确定常量类型,即使用const关键字是没有:=这个语法的,你只能用两种类型,如下:
const s = "constant" const h = 500000000 const i = 3e20 / h
1.2循环
GO语言中只有一种循环,for循环,基本用法有如下几种
死循环
for { fmt.Println("loop") break }
基本的条件循环
for j := 7; j < 9; j++ { fmt.Println(j) }
for循环中的三条判断语句可以少任意一条或两条,和Cpp,Python可以使用break和continue来中断循环
1.3选择
没啥好说的,就普通的if,else,但没有括号,且if后面必须直接加{
if 7%2 == 0 { fmt.Println("7 is even") } else { fmt.Println("7 is odd") }
这样就不行
if 7%2 == 0 { fmt.Println("7 is even") }
但是else的{}可以放下来,但不建议
1.4 分支
Switch分支,与C++不同,不需要加break也会自动退出,golang中的Switch接受字符串等字符类型,可以不加Switch的判断条件,直接在每个case里写判断条件代替,if语句,很清楚,Switch开始判断,case结果,不满足default
switch a { case 1: fmt.Println("one") case 2: fmt.Println("two") case 3: fmt.Println("three") case 4, 5: fmt.Println("four or five") default: fmt.Println("other") } t := time.Now() switch { case t.Hour() < 12: fmt.Println("It's before noon") default: fmt.Println("It's after noon") }
1.5数组
没啥好说的,就数组
func main() { var a [5]int a[4] = 100 fmt.Println("get:", a[2]) fmt.Println("len:", len(a)) b := [5]int{1, 2, 3, 4, 5} fmt.Println(b) var twoD [2][3]int for i := 0; i < 2; i++ { for j := 0; j < 3; j++ { twoD[i][j] = i + j } } fmt.Println("2d: ", twoD)}
未赋值就输出0,数据用的很少,主要原因是因为长度固定
1.6切片(slice)
没听过,按课的意思,像是vector动态数组
可以在任意时刻更改长度
s := make([]string, 3) s[0] = "a" s[1] = "b" s[2] = "c" fmt.Println("get:", s[2]) // c fmt.Println("len:", len(s)) // 3
关键字看样子是用make来定义,查了一下
make 是一个内置函数,用于创建切片(slice)、映射(map)和通道(channel)类型的实例。它的主要作用是为这些类型分配内存,并对其进行初始化。
make([]T, len, cap)
T是切片元素的类型。len是切片的长度,即切片当前包含的元素个数。cap是切片的容量,即切片可以存储的最大元素个数。如果没有指定cap,则其默认值等于len。
s := make([]string, 3)
那这句代码就是,创建一个字符串切片,长度为3,最大容量为3,但是实际上感觉容量这个参数用处不大,因为到了容量上限,定义的切片会自动扩容
AI对扩容的解释
当你向切片中添加元素时,如果切片的长度还没有达到容量,那么新元素会被添加到切片的末尾,切片的长度会增加。但是,如果切片的长度已经达到了容量,那么再添加新元素时,Go会自动创建一个新的底层数组,其容量是原来的两倍,并将原来的元素复制到新数组中,然后再添加新元素。这个过程称为切片的扩容。
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s) // [a b c d e f]
可以使用append加入元素,有点像Python的list,但因为有扩容这段,需要将append后的数据赋值给原切片,同样可以使用Python的数列切片手段
fmt.Println(s[2:5]) // [c d e]
fmt.Println(s[:5]) // [a b c d e]
fmt.Println(s[2:]) // [c d e f]
1.7 map
就字典,感觉和C++一样
创建
m := make(map[string]int) m["one"] = 1 m["two"] = 2
删除
delete(m, "one")
但是有一点注意,它的字典是纯随机的,对于不存在的值返回0
1.8range
有点像enumerate,配合for一起用,不做过多笔记,没啥说的
func main() { nums := []int{2, 3, 4} sum := 0 for i, num := range nums { sum += num if num == 2 { fmt.Println("index:", i, "num:", num) // index: 0 num: 2 } } fmt.Println(sum) // 9 m := map[string]string{"a": "A", "b": "B"} for k, v := range m { fmt.Println(k, v) // b 8; a A } for k := range m { fmt.Println("key", k) // key a; key b }}
输出
index: 0 num: 2
9
a A
b B
key a
key b
1.9函数
比较特殊的一点,要指明返回值类型
func add2(a, b int) int { return a + b}
一般都会返回两个值,一个是正确值,一个是错误信息
func exists(m map[string]string, k string) (v string, ok bool) { v, ok = m[k] return v, ok}
1.10 指针
定义用*,主要用途,对常用的参数进行修改,因为进入函数的参数是拷贝值,因此需要用指针指向原地址,没记错的话,和C++好像是一样的
func add2(n int) { n += 2}func add2ptr(n *int) { *n += 2}func main() { n := 5 add2(n) fmt.Println(n) // 5 add2ptr(&n) fmt.Println(n) // 7}
1.11 结构体
定义一个结构体
type user struct { name string password string}
a := user{name: "wang", password: "1024"} b := user{"wang", "1024"} c := user{name: "wang"} c.password = "1024" var d user d.name = "wang" d.password = "1024"
它的名字叫user,有两个字段,name和password
剩下的和Python差不多,不写了
1.12 错误
有点像Python里抛出错误的语法,应该是raise ValueError
不写了,就是注意返回的时候多加一个值,没错就正常返回,写一个错误如下
errors.New("not found")
新错误找不到
1.13字符串
有一些操作,在API中可以找到,不再11列举
包括字符串的格式化,Python中的format,很简单就不列举了
1.14json
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于JavaScript的一个子集,易于人阅读和编写,同时也易于机器解析和生成。在Go语言中,encoding/json包提供了对JSON数据的编码和解码功能。
JSON操作主要包括以下几个方面:
-
编码(Marshal):将Go语言中的数据结构转换为JSON格式的字节序列。这通常用于将数据发送到其他系统或存储到文件中。
-
解码(Unmarshal):将JSON格式的字节序列转换为Go语言中的数据结构。这通常用于从其他系统接收数据或从文件中读取数据。
-
格式化(MarshalIndent):与编码类似,但会将JSON数据格式化为更易读的形式,通常用于调试或输出到控制台。
-
解析(Decode):从输入流(如文件或网络连接)中读取JSON数据并解码到Go语言的数据结构中。
-
编码到Writer:将JSON数据编码并直接写入到
io.Writer接口的实现中,如os.File或bytes.Buffer。 -
解码从Reader:从
io.Reader接口的实现中读取JSON数据并解码到Go语言的数据结构中
你只需要保证每个结构体中的字段的第一个字母是大写,就可以对这个结构体进行json化
buf, err := json.Marshal(a)
只看关键代码。返回两个变量,buf是数列化后的结果,这个在上面的那段字里已经说过了
1.15time
看时间,需要注意的只有一点,格式化时间使用一个特定的字符串时间
t.Format("2006-01-02 15:04:05")
字符串里的时间是不能改的,一旦改了,输出的时间就不对
1.16字符串和数字的转换
strconv包,用法很多,但都很简单
n, _ := strconv.ParseInt("11", 10, 64)
三个参数,第一个要转换的数,第二个进制,第三个数据类型
1.17 进程信息 环境变量
os库,可以获取进程运行时的命令行参数
os.Getenv获取环境变量
os.Setenv设置环境变量,
fmt.Println(os.Setenv("AA", "BB"))
这个就是设置AA为BB
exec.Command启动子进程