type User struct { // 结构体属性的首字母是大写,为共有属性.首字母是小写,为私有属性. Username string Age int skin string// 私有属性 } funcmain() { u := User{Username: "tom", Age: 18} u2 := User{"jerry", 18} // key 可以省略,结构体的顺序是固定的 }
funcmain() { a := Animal{"tom", 18} a.Eat() // Human Eat a.Run() // Human Run // 两种方式 d := Dog{Animal{"旺财", 20}, skin: "yellow"} // or var d Dog d.name = "旺财" d.age = 20 d.skin = "yellow" d.Eat() // Human Eat d.Run() // Dog Eat d.Bark() // Dog 汪 }
Interface
数组
[n]T
var a [2]int// 表示变量 a 为两个整数类型的数组 a[0] = 1 a[1] = 2 b := [2]string{"hello", "world"} // 变量 b 为两个字符串类型的数组,并为其定义了初始值 c := [...]int{1, 2, 3} // 长度为 3 的数组,... 根据实际数量设置长度
// 使用 func 声明函数,形参的类型需写在形参后 funcadd(a int, b int)int { return a + b }
// 连续有多个函数形参类型相同时,除了最后一个类型外,其他的可以省略 funcadd(a, b int)int { return a + b }
// 多返回值 funcfn(a string, b int) (string, int) { return a, b }
funcfn2(a string, b int) (c int, d int) { // 给有名称的返回值变量赋值 c = 888 d = 666 // 返回值已经声明,不需要在 return 后写 return } funcfn2(a string, b int) (c int, d int) { c = 888 d = 666 return1, 2// 此处返回 1, 2 回覆盖声明的返回 } // 同形参一样可以省略除最后一个类型外的其他类型 funcfn2(a string, b int) (c, d int) { c = 888 d = 666 return }
可变参数函数
// numbers 为 int 的数组(切片) funcsum(numbers ...int)int { total := 0 for _, n := range numbers { total += n } return total } funcmain() { fmt.Println(sum(1, 2)) fmt.Println(sum(1, 2, 3)) num := []int{1, 2, 3, 4} // ... 和 JS 的解构类似,不过 GO 的 ... 在变量后 fmt.Println(sum(num...)) }
匿名函数
sum := func(a, b int)int { return a + b } sum(1, 2)
// 声明一个匿名函数并立即调用 func(a, b int)int { return a + b }(1, 2)
指针
指针保存了值的内存地址,类似于 JS 中的引用类型
funcswap(x *int, y *int) { var temp int temp = *x *x = *y *y = temp } funcmain() { a := 1 b := 2 swap(&a, &b) fmt.Println("a:", a, "b:", b) // a: 2 b: 1 }
类型 *T 是指向 T 类型值的指针。其零值为 nil
& 操作符会生成一个指向其操作数的指针
i := 1 p = &i // p 是一个指针,指向 i 的地址 fmt.Println(p) // 直接打印指针 p 获取的是指针的地址:0x1400001c0d0 fmt.Println(&i) // 通过取址符 & 获取 i 的地址:0x1400001c0d0 fmt.Println(*p) // 通过 * 获取指针的值:1 fmt.Println(&p) // 通过取址符 & 获取指针 p 的地址:0x1400000e028
* 操作符表示指针指向的底层值
fmt.Println(*p) // 通过指针 p 读取 i。通过 * 操作符 *p = 21// 通过指针 p 设置 i
defer
defer 关键字会将函数推迟到外层函数返回之后执行。
推迟的函数调用会被压入一个栈中。当外层函数返回时,被推迟的函数会安装后近先出的顺序调用
推迟调用的函数其参数会立即求值,但直到外层函数返回前该函数都不会被调用。
fmt.Println("counting") for i := 0; i < 3; i++ { defer fmt.Println(i) } fmt.Println("done") // counting // done // 2 最后被压入栈首先执行 // 1 第二个被压入栈 // 0 最先被压入栈最后执行
go mod download # 下载 go.mod 文件中指明的所有依赖 go mod edit # 编辑 go.mod 文件 go mod graph # 查看现有的依赖结构 go mod init # 生成 go.mod 文件 go mod tidy # 整理现有的依赖 go mod vendor # 导出项目所有的依赖到vendor目录 go mod verify # 校验一个模块是否被篡改过 go mod why # 查看为什么需要依赖某模块
go 相关命令
go version # 查看版本 go env# 查看环境变量 go env -w GO111MODULE=on # 设置 GO111MODULE # aoto: 默认值, 项目包含 go.mod 文件时启用 Go modules. on: 启用, 推荐设置. off: 禁用 go env GO111MODULE # 查看设置 go env -w GOPROXY=https://goproxy.cn,direct # 设置代理, 也可以把 GOPROXY=https://goproxy.cn,direct 加到 go 命令前来临时使用. 如: GOPROXY=https://goproxy.cn,direct go mod tidy go env GOPROXY # 查看代理