类型和结构体都可以定义方法,可被调用
一 :配置 GOPROXY加速
Linux
# 启用 Go Modules 功能 go env -w GO111MODULE=on # 配置 GOPROXY 环境变量,以下三选一 # 1. 七牛 CDN go env -w GOPROXY=https://goproxy.cn,direct # 2. 阿里云 go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct # 3. 官方 go env -w GOPROXY=https://goproxy.io,direct # 确认一下: $ go env | grep GOPROXY GOPROXY="[https://goproxy.cn](https://goproxy.cn/)"
Bash
Win
# 启用 Go Modules 功能 $env:GO111MODULE="on" # 配置 GOPROXY 环境变量,以下三选一 # 1. 七牛 CDN $env:GOPROXY="https://goproxy.cn,direct" # 2. 阿里云 $env:GOPROXY="https://mirrors.aliyun.com/goproxy/,direct" # 3. 官方 $env:GOPROXY="https://goproxy.io,direct" # 确认一下: $ go env | findstr GOPROXY GOPROXY="[https://goproxy.cn](https://goproxy.cn/)"
PowerShell
二: 常用包
可以给包别名从而实现避免命名冲突
import fm “fmt”
fmt : C 的 printf 和 scanf 的功能实现格式化的 I/O 包
rand : 伪随机数的生成
strings : 简单的函数来操作 UTF-8 编码的字符串。
time : 提供了测量和显示时间的功能
三 : 入门
导包制
import “”
变量声明 名前 类后
单个 := 局部变量
var variable DataTypes // 显式
name := "string" // 隐式短声明 !!!全局变量不可用
GO
多个 其他定义的也可使用
// 不同之一
var (
s1 string = "1";
s2 string = "2";
)
GO
常量 const
// 允许并行赋值 const beef, two, c = "eat", 2, "veg" const Monday, Tuesday, Wednesday, Thursday, Friday, Saturday = 1, 2, 3, 4, 5, 6 const ( Monday, Tuesday, Wednesday = 1, 2, 3 Thursday, Friday, Saturday = 4, 5, 6 ) // 可使用枚举 const ( Unknown = 0 Female = 1 Male = 2 )
GO
类型转换
value_Of_TypeB = typeB(value_Of_TypeA)
外部访问 首字母大写的变量 函数 可被外面的包访问
输入/输出
引入 fmt 包
fml.printf("%v 你好吖", wood) %v是任意匹配数据类型 特有其他基础和C差不多
%#v 可以将空的字符串打印出来 "" 原始的指
var f = fml.Sprintf("%v 你好吖", wood)
fmt.printf(f)
// 输入使用
var name string
fmt.Scan(&name)
GO
数据类型与关键词
byte 单字节
rune 8字节
自定义数据类型
type Code int type Number interface{ int|uint|int8|int16 } const ( SuccessCode Code = 0 ValidCode Code = 7 // 校验失败的错误 ServiceErrCode Code = 8 // 服务错误 ) func (c Code) GetMsg() string { // 可能会有更加响应码返回不同消息内容的要求,我们在这个函数里面去实现即可 // 可能还会有国际化操作 return "成功" } func main() { fmt.Println(SuccessCode.GetMsg()) var i int fmt.Println(int(SuccessCode) == i) // 必须要转成原始类型才能判断 }
GO
自定义类型别名
type Code = int
- 不能绑定方法
- 打印类型还是原始类型
- 和原始类型比较,类型别名不用转换
关键词
_ | 空白识别符 : 任何赋给这个标识符的值都将被抛弃 |
---|---|
nil | 类似于Null 空值 |
const | 声明常量 |
var | 声明变量 |
type | 定义结构体? |
lota | 遇到一个变量会+1 遇到常量guilubg3 |
break | 跳出当前的执行 |
运算符 同C
位移存在 1 << 10 10 >> 1
数组
var arrlist [i]Datatype = [i]Datatype{} var nameList []Datatype nameList = append(nameList, "") nameList = append(nameList, "") var nameList []string = []string{} nameList = make([]string, 0) || /* 不需要上面初始化 */ nameList := make([]string, 0) make([]Datatype, length, capacity)
GO
切片 slice 可变长度的固定type 数组
S := []int{1,2,3,4,5,6}
s1 := S[:3] // 从前三个取
s2 := S[3:] // 从后三个取
var nameList []string
nameList = append(nameList, "")
nameList = append(nameList, "")
GO
指针
& 取值符号
- 解引用 将值指向原地址
func main() {
s := "good bye"
var p *string = &s
*p = "ciao"
fmt.Printf("Here is the pointer p: %p\n", p) // prints address
fmt.Printf("Here is the string *p: %s\n", *p) // prints string
fmt.Printf("Here is the string s: %s\n", s) // prints same string
}
func Expo
GO
结构体指针
type Student struct { Name string Age int } func SetAge(info Student, age int) { info.Age = age } func SetAge1(info *Student, age int) { info.Age = age } func main() { s := Student{ Name: "枫枫", Age: 21, } fmt.Println(s.Age) SetAge(s, 18) fmt.Println(s.Age) SetAge1(&s, 17) fmt.Println(s.Age) }
GO
type Student struct { Name string Age int } func (s Student) SetAge(age int) { s.Age = age } func (s *Student) SetAge1(age int) { s.Age = age } func main() { s := Student{ Name: "枫枫", Age: 21, } s.SetAge(18) fmt.Println(s.Age) s.SetAge1(18) fmt.Println(s.Age) }
GO
map 映射
// 初始化 var aMap = make(map[string]string) var aMap = map[string]string{} var usrMap map[int]string = map[int]string{ 1: "wood", 2: "bird", } fmt.Println(usrMap) fmt.Println(usrMap[1]) fmt.Println(usrMap[2]) fmt.Printf("%#v\n", usrMap[4]) valuse , static = userMap[4] // valuse是 map[int]string 这里定义的string // static 是bool 判断是否有值 delete(usermap, key值) -------------------------------- map[1:wood 2:bird] wood bird ""
GO
结构体
type People struct { Time string } func (p People) Info() { fmt.Println("people ", p.Time) } // Student 定义结构体 type Student struct { People Name string Age int } // PrintInfo 给机构体绑定一个方法 func (s Student) PrintInfo() { fmt.Printf("name:%s age:%d\n", s.Name, s.Age) } func main() { p := People{ Time: "2023-11-15 14:51", } s := Student{ People: p, Name: "枫枫", Age: 21, } s.Name = "枫枫知道" // 修改值 s.PrintInfo() s.Info() // 可以调用父结构体的方法 fmt.Println(s.People.Time) // 调用父结构体的属性 fmt.Println(s.Time) // 也可以这样 }
GO
结构体标签
type Student struct { Name string `json:"name"` // Name -> name Age int `json:"age"` } func main() { s := Student{ Name: "枫枫", Age: 21, } byteData, _ := json.Marshal(s) fmt.Println(string(byteData)) }
GO
接口
type SingInterface interface { Sing() GetName() string } type Chicken struct { Name string } func (c Chicken) Sing() { fmt.Println(c.Name, "Sin") } func (c Chicken) GetName() string { return c.Name } type Cat struct { Name string } func (c Cat) Sing() { fmt.Println(c.Name, "Sing") } func (c Cat) GetName() string { return c.Name } /* func sing(c Chicken) { c.Sing() // 把Chicken 类型改为接口 } */ func sing(c SingInterface) { c.Sing() ch, static(状态) := c.(chicken) // 类型断言 或 switch name := c.(type){ case Chicken: fmt.Println(name) case Cat: fmt.Println(name) default: fmt.Println("其他") } fmt.Println(c.GetName()) } func main() { c := Chicken{Name: "kunKun"} ch := Cat{Name: "Mimi"} sing(c) sing(ch) }
GO
空接口
空接口可以接收任何类型
type name interface{}
func PrintZ(test interface{} ) {
fmt.Println(test)
}
GO
泛型
泛型函数
func add[T int | float64 | int32](a, b T) T {
return a + b
}
GO
泛型结构体
type Responsed[T any] struct { Code int `json:"code"` Msg string `json:"msg"` Date T `json:"date"` } func main() { type User struct { Name string `json:"name"` } type UserInfo struct { Name string `json:"name"` Age int `json:"age"` } var userResponse Responsed[User] var userInfoResponse Responsed[UserInfo] json.Unmarshal([]byte(`{"code":0,"msg":"sure","date":{"name":"wood"}}`), &userResponse) fmt.Println(userResponse.Date.Name) json.Unmarshal([]byte(`{"code":0,"msg":"sure","date":{"name":"fake","age":18}}`), &userInfoResponse) fmt.Println(userInfoResponse.Date.Name, userInfoResponse.Date.Age) }
GO
四:terminal 操作
- 格式化代码
gofmt –w .go 格式化并覆盖
gofmt -r '(a) -> a' –w *.go 将code中的 (a) 替换为 a
PowerShell
- 查看代码文档
go doc package xx函数 可以查看具体包 具体函数用法
PowerShell
- 安装第三方包
go install
PowerShell
- 升级版本
go fix
PowerShell
- 单元测试
测试文件命名为 xxx_test.go
go test
PowerShell
五: 函数
首字母大写可被外部调用
返回零值(或 nil)和 false 表示失败
// 有参有返回值的 func test(Datatype parameter)(return_datatype,return_datatype){ // code....... return value,values ] // 优先级 >> main 函数 // 初始化函数 func init() { } // 引用传递 func DoSomething(a *A) { b = a // 通过指针传递,原始对象可以被修改,且 b 持有有效的指针引用。 } func DoSomething(a A) { b = &a // 通过值传递,原始对象不会被修改 } // 多个重复参数 func add(numberList ...int){ } // 署名函数 func { var getName = func() (name string) { name = "wood" return } fmt.Println(getName()) } go func() { ... }()
GO
高阶函数
// _是函数名 == fun的名称 -> 1,2,3
var funMap = map[int]func _ (){
1: login,
2: register,
3: exit,
}
fun, ok := funMap[index]
if ok{
fun()
}
GO
闭包
func AwaitAdd(awaitSecond int) func(...int) int {
{
return func(numberList ...int) (sum int) {
for _, number := range numberList {
sum += number
}
return sum
}
}
}
GO
defer 函数
return 之前执行
距离return近谁先执行
用作与资源清理
在函数体执行完毕后再执行
六 : 流程控制
1. 条件
// 可以直接初始化变量用 if err := file.Chmod(0664); err != nil { fmt.Println(err) return err } switch var1 { case var1: // code case var2: // code2 fallthrough; // 执行当前的接着执行下一个 case var3: // code3 default: }
GO
2.循环
continue : 忽略剩余的循环体而直接进入下一次循环
Tag :标签功能 大写
LABEL1: for i := 0; i <= 5; i++ { for j := 0; j <= 5; j++ { if j == 4 { continue LABEL1 // continue 指向LABEL1 跳转执行该标签内容 } fmt.Printf("i is: %d, and j is: %d\n", i, j) } } }
GO
for i := 0; i < 5; i++ { // code } for i, j := 0, N; i < j; i, j = i+1, j-1 {} for i:=0; i<5; i++ { for j:=0; j<10; j++ { println(j) } } // 无条件循环 == while for{} // for-range == foreach // 遍历 str := "Go is a beautiful language!" fmt.Printf("The length of str is: %d\n", len(str)) for pos, char := range str { fmt.Printf("Character on position %d is: %c \n", pos, char) // pos 是index索引 char 指向的内容 for index, rune := range str2 { fmt.Printf("%-2d %d %U '%c' % X\n", index, rune, rune, rune, []byte(string(rune)))
GO
七: 多线程
var wait sync.WaitGroup func main() { starttime := time.Now() wait.Add(3) go shopping("wood", &wait) go shopping("fuck", &wait) go shopping("cat", &wait) wait.Wait() fmt.Println("完成购买", time.Since(starttime)) } func shopping(name string, wait *sync.WaitGroup) { fmt.Printf("%s 开始购物\n", name) time.Sleep(1 * time.Second) fmt.Printf("%s 结束\n", name) wait.Done() }
GO
channer 信道
var waat sync.WaitGroup var moneyChan = make(chan int) func main() { starttime := time.Now() waat.Add(3) go pay("wood", 2, &waat) go pay("fuck", 5, &waat) go pay("cat", 3, &waat) go func() { waat.Wait() close(moneyChan) }() for true { money, ok := <-moneyChan fmt.Println(money, ok) if !ok { break } } // or for money := range moneyChan { fmt.Println(money) } fmt.Println("完成购买", time.Since(starttime)) } func pay(name string, money int, wait *sync.WaitGroup) { fmt.Printf("%s 开始购物\n", name) time.Sleep(1 * time.Second) fmt.Printf("%s 结束\n", name) moneyChan <- money waat.Done() }
GO
select
var waat1 sync.WaitGroup var moneyChan1 = make(chan int) var nameChan = make(chan string) var doneChan = make(chan struct{}) func main() { starttime := time.Now() waat1.Add(3) go send("wood", 2, &waat1) go send("fuck", 5, &waat1) go send("cat", 3, &waat1) go func() { defer close(moneyChan1) defer close(nameChan) defer close(doneChan) waat1.Wait() }() var moneyList []int var nameList []string var event = func() { for { select { case money := <-moneyChan1: moneyList = append(moneyList, money) case name := <-nameChan: nameList = append(nameList, name) case <-doneChan: return } } } event() fmt.Println("完成购买", time.Since(starttime)) fmt.Println(nameList) fmt.Println(moneyList) }
GO
超时处理 Timeout
var done = make(chan struct{}) func event() { fmt.Println("event开始执行") time.Sleep(2 * time.Second) fmt.Println("event执行完毕") close(done) } func main() { go event() select { case <-done: fmt.Println("协程执行完毕") case <-time.After(1 * time.Second): fmt.Println("超时") return } }
GO
线程安全 lock
var sum2 int var lock sync.Mutex var wait2 sync.WaitGroup func add1() { lock.Lock() for i := 0; i < 10000; i++ { sum2++ } lock.Unlock() wait2.Done() } func sub1() { lock.Lock() for i := 0; i < 10000; i++ { sum2-- } lock.Unlock() wait2.Done() } func main() { wait2.Add(2) go add1() go sub1() wait2.Wait() fmt.Println(sum2) }
GO
Map.sync
var wait6 sync.WaitGroup var mp1 sync.Map func read() { for { fmt.Println(mp1.Load("time")) } wait6.Done() } func writer1() { for { mp1.Store("time", time.Now().Format("2006-01-02 15:04:05")) } wait6.Done() } func main() { wait6.Add(2) go read() go writer1() wait6.Wait() }
GO
八 : 异常处理
向上抛
func div(a, b int) (res int, err error) { if b == 0 { err = errors.New("division by zero") return } res = a / b return } func server() (res int, err error) { res, err = div(10, 0) if err != nil { return } res++ res += 2 return } func main() { res, err := server() if err != nil { fmt.Println(err) return } fmt.Println(res) }
GO
中断程序
func init() {
_, err := os.ReadFile("dddd")
if err != nil {
println("error")
}
}
func main() {
fmt.Println("hello world")
}
GO
恢复程序
func reading() { defer func() { err := recover() if err != nil { fmt.Println(err) fmt.Println(string(debug.Stack())) } }() var list []int = []int{1, 2} fmt.Println(list[1]) } func main() { reading() fmt.Println("正常执行") }
GO
IX. 文件流
1. FileRead
一次性读取
func ReadAtOnce() {
file, err := os.ReadFile("E:\\code\\go\\file\\text.txt")
if err != nil {
println(error.Error(err))
}
fmt.Println(string(file))
}
GO
分片读取
func ShardReading() { file, err := os.Open("E:\\code\\go\\file\\text.txt") if err != nil { panic(err) } defer file.Close() for { var byteData = make([]byte, 12) n, err := file.Read(byteData) if err == io.EOF { break } fmt.Println(string(byteData[:n])) } }
GO
缓冲读取
func BufRead() { file, err := os.Open("E:\\code\\go\\file\\text.txt") if err != nil { panic(err) } defer file.Close() buf := bufio.NewReader(file) for { text, _, err := buf.ReadLine() if err == io.EOF { break } fmt.Println(string(text)) } }
GO
缓冲选词
func BufRead2() { file, err := os.Open("E:\\code\\go\\file\\text.txt") if err != nil { panic(err) } defer file.Close() buf := bufio.NewScanner(file) buf.Split(bufio.ScanWords) var index int for buf.Scan() { index++ fmt.Println(index, buf.Text()) } }
GO
2. FileWrite
func main() { file, err := os.OpenFile("w.txt", os.O_RDWR|os.O_CREATE, 0777) if err != nil { panic(err) } defer file.Close() byteData, err := io.ReadAll(file) if err != nil { fmt.Println(err) return } fmt.Println(string(byteData)) err = os.WriteFile("w.txt", []byte("hi"), 0777) fmt.Println(err) file1, err1 := os.Open("C:\\Users\\34659\\Pictures\\117922308_p0_master1200.jpg") if err1 != nil { fmt.Println(err1) return } defer file1.Close() wfile, err2 := os.OpenFile("girl.jpg", os.O_WRONLY|os.O_CREATE, 0777) if err2 != nil { fmt.Println(err2) return } defer wfile.Close() io.Copy(wfile, file1) }
GO
X : 单元测试
文件要以 _test.go 为后缀
func TestAdd(t *testing.T) {
if ans := Add(1, 2); ans != 3 {
t.Errorf("Add(1, 2) = %d; want 3", ans)
}
if num := Add(4, 5); num != 8 {
t.Errorf("Add(4,5) = %d; want 8", num)
}
GO
子测试
func TestAdd(t *testing.T) { t.Run("add1", func(t *testing.T) { if ans := Add(1, 2); ans != 3 { t.Errorf("Add(1, 2) = %d; want 3", ans) } }) t.Run("add2", func(t *testing.T) { if num := Add(4, 5); num != 8 { t.Errorf("Add(4,5) = %d; want 8", num) } }) }
GO
Log | 打印日志, 结束测试 | PASS |
---|---|---|
Logf | 格式化输出日志, 同时结束测试 | PASS |
Error | 打印错误日志,结束测试 | FAIL |
Errorf | FAIL | |
Fatal | 打印致命日志,同时结束 | FAIL |
FatalF | FAIL |
TestMain
func setup() { fmt.Println("setup") } func teardown() { fmt.Println("teardown") } func Test1(t *testing.T) { fmt.Println("Test1") } func Test2(t *testing.T) { fmt.Println("Test2") } func TestMain(m *testing.M) { setup() code := m.Run() teardown() os.Exit(code) }
GO
XI.与其他语言进行交互
https://learnku.com/docs/the-way-to-go/interact-with-other-languages/3581
XII: 反射
判断类型
func refType(obj any) { typeObj := reflect.TypeOf(obj) fmt.Println(typeObj, typeObj.Kind()) tp := typeObj.Kind() // 判断类型 switch tp { case reflect.Slice: fmt.Println("切片") case reflect.Map: fmt.Println("map") case reflect.Struct: fmt.Println("struct") case reflect.String: fmt.Println("string") } } func main() { refType(struct { Name string }{Name: "wood"}) name := "wood" refType(name) refType([]string{"wood"}) name1 := "风"
GO
获取值
func reflectionGetValues(obj any) { value := reflect.ValueOf(obj) fmt.Println(value.Type()) switch value.Kind() { case reflect.Int: fmt.Println(value.Int()) case reflect.Struct: fmt.Println(value.Interface()) case reflect.String: fmt.Println(value.String()) } } func main(){ reflectionGetValues(44) }
GO
修改值
func reflectionSetValues(obj any) { value := reflect.ValueOf(obj) elem := value.Elem() // 专门取指针反射的值 switch elem.Kind() { case reflect.String: elem.SetString("枫枫知道") } } func main() { reflectionSetValues(&name1) fmt.Println(name1) }
GO
群友到此一游