1-开发环境与语法速学
环境配置
ubuntu 22.04 aarch64
# 下载安装包
curl -OL https://golang.org/dl/go1.17.3.linux-arm64.tar.gz
# 解压
sudo tar -C /usr/local -xvf go1.17.3.linux-arm64.tar.gz
# ~/.zshrc 添加环境变量
export PATH=$PATH:/usr/local/go/bin
# 验证安装
go version
# 配置代理
go env -w GOPROXY=https://goproxy.cn,direct
安装 vscode 依赖 aldijav.golangwithdidi go工具 例如自动引入,格式化,跳转源代码等, vscode需要用到,但vscode自己总是下载失败 go install -v github.com/ramya-rao-a/go-outline@v0.0.0-20210608161538-9736a4bde949 go install -v golang.org/x/tools/cmd/goimports@latest go install -v github.com/stamblerre/gocode@v1.0.0 go install -v github.com/rogpeppe/godef@v1.1.2
go 没有繁琐的eslint和prettier 统一代码规范 go 包的概念很方便 go 的学习主要靠源码 包括gin框架 go 中首字母大写会被默认导出 go 中变量名一般用一个字母 go 程序员很爱用缩写 server => srv 把原音字母去掉就是简写 例如 migrate => mgrt
hello 程序
package main
import "fmt"
func main() {
fmt.Println("GO-The Better C")
}
go build . 找到当前目录下的入口文件,编译为 linux 可执行的二进制文件 ./hello 执行程序 go run . 相当于 go build . && ./hello
变量与常量
var a = 1
// 类型可选
var b int = 3
var c, d int = 8, 9
var (
e = 1
f = 2
)
// 冒等 不能写类型
g := 1
h, i := 2, 3
fmt.Println(a, b, c, d, e, f, g, h, i)
// 常量
// 第一次出现 iota 的地方是 0
// 语法糖:同样的语句会原封不动复制下去
const (
C0 = iota + 1
_
C1
C2
)
const (
A0 = 1 << iota
A1
A2
A3
)
fmt.Println(A0, A1, A2, A3)
// iota 默认为 0,每出现一次就加 1,只能用在 const() 中
// 每个 const 会重置 iota
for循环
// for 循环不加括号
// for后不接表达式,等价于js 的while(true),等待break关键字
a := 1
for {
if a > 2 {
break
}
a++
fmt.Println(a)
}
// for后接一个表达式等价于js的while(condition)
b := 2
for b < 3 {
fmt.Println(b)
b++
}
// for后接三个表达式等价于js的for
for c := 1; c < 3; c++ {
fmt.Println(c)
}
条件语句
// if else 不加括号
// if 接一个表达式等价于js的 if(condition)
// if 接两个表达式(变量的初始化,但变量作用域仅限于ifelse中)
if num := 1; num < 0 {
fmt.Println(num, "负数")
} else if num < 10 {
fmt.Println(num, "一位数")
} else {
fmt.Println(num, "多位数")
}
switch time.Now().Weekday() {
case time.Saturday, time.Sunday: // 一个case可以有多个值
fmt.Println("休息日")
fallthrough // 继续执行
// 默认 break
default:
fmt.Println("工作日")
}
函数
package main
import "fmt"
func main() {
// 函数中不能定义具名函数,但可以定义匿名函数,然后赋值给变量
add := func(a, b int) (int, int) {
return a + b, a * b
}
// 匿名函数也可以直接调用
result := func(a, b int) int {
return a + b
}(1, 2)
fmt.Println(result)
fmt.Println(add(1, 2))
fmt.Println(f1(1, 2))
sum, multi := f2(1, 2)
fmt.Println(sum, multi)
nums := []int{1, 2, 3, 4}
fmt.Println(sumfunc(nums...))
}
// 具名函数
func f1(x, y int) (int, int) {
// 可以返回多个值
return x + y, x * y
}
// 返回值类型定义时也可以声明变量
// 返回语句可以省略
func f2(x, y int) (sum, multi int) {
sum = x + y
multi = x * y
return
}
// 可变参数函数
func sumfunc(numbers ...int) int {
total := 0
for _, n := range numbers {
total += n
}
return total
}
数据类型
数据类型分为值类型和引用类型
- 值类型:该类型的变量直接存放值
- 引用类型:该类型的变量不直接存放值,而是存放值的地址和其他信
值类型分为简单值类型与复杂值类型
简单值类型
- 数字(14种)int8 ... int128 float32 float64
- 如果单独声明 int 跟随操作系统,如果是64位 那么int表示int64
- 字符串 string 双引号
- 字符 rune 单引号 打印出来是字符对应的编码
- 布尔 boolean true | false
var a int8 = 10
var b int = 11
var c float32 = 64
var d string = "hi"
var e rune = 'h'
f := 'a'
复杂值类型
结构体
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string
Age int
}
type User2 struct {
ID string `json:"id"`
UserName string `json:"username"`
Email string `json:"email"`
}
func modify(u *User) {
u.Age = 20
}
func main() {
u := User{Name: "gsq", Age: 11}
u.Name = "zs"
u1 := u
u1.Name = "gsq"
fmt.Println(u1)
u2 := User{"gsq", 11}
modify(&u2)
fmt.Println(u, u2, u.Name, u.Age)
u3 := User2{ID: "1001", UserName: "gsq", Email: "@qq"}
fmt.Println(u3)
// 序列化
bytes, error := json.Marshal(u3)
if error != nil {
panic(error)
}
fmt.Println(string(bytes))
}
// 复杂值类型
// 结构体 struct
// 用于类型定义,类似 ts 中的类型定义
// 1, 结构体是值类型,不是引用类型
// 实际上结构体 u 就是一个固定长度的值,由 type 中定义的几部分字段拼接而成
// 结构体的属性名称推荐大驼峰 UserName
// 2. Go只支持值传递,不过可以把地址当作值 function(&user)
// 而 js 可以自动获取对象的地址
// 作为参数时会拷贝一份,在函数中修改结构体的属性值,不会影响原来的结构体
// 如果想在函数中改变结构体的某个属性
// 需要传递结构体的地址,同时在函数类型定义中也要注明参数的类型为地址
// & 与 * 取址号
// 用于类型
// var a *int 表示 a 存 int 类型值的地址,此时称 a 为指针
// 用于值
// &b 表示变量b的地址
// *c 表示指针 c 对应的值
// 3. 结构体支持 label,用于序列化或者字段映射等功能
数组
package main
import "fmt"
func main() {
a := [5]int{1, 2, 3, 4, 5}
b := [3]string{"1", "2"} // 根据类型默认补全
c := [...]int{1, 1, 1} // 不确定长度,使用...
fmt.Println(a, b, len(c))
}
// 数组是值类型
// 数组长度是固定的
// len(arr)获取数组长度