类型和结构体都可以定义方法,可被调用

一 :配置 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

二: 常用包

https://pkg.go.dev/

可以给包别名从而实现避免命名冲突

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

  1. 不能绑定方法
  2. 打印类型还是原始类型
  3. 和原始类型比较,类型别名不用转换

关键词

_空白识别符 : 任何赋给这个标识符的值都将被抛弃
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 操作

  1. 格式化代码
gofmt –w .go 格式化并覆盖
gofmt -r '(a) -> a' –w *.go  将code中的 (a) 替换为 a 
PowerShell
  1. 查看代码文档
go doc package xx函数 可以查看具体包 具体函数用法
PowerShell
  1. 安装第三方包
go install 
PowerShell
  1. 升级版本
go fix
PowerShell
  1. 单元测试

测试文件命名为 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

结构体反射