是谁 2024 年才开始学 go?哦,原来是我

结构体

type Person struct {
    name string
    age int32
}

person := Person{
    name: "Name",
    age: 3
}

数组

arr := []int32{1, 2, 3}

arr[1] = 200

// push
arr = append(arr, 4, 5)
// unshift
arr = append([]int32{-1, 0}, arr...)
// pop
arr = arr[0 : len(arr) - 1]
// shift
arr = arr[1:]

遍历

// go 语言钟可以用多个变量接收多个值
for index, item := range arr {
    fmt.Println(index, item)
}

// 如果有些返回的值是无用的,可以用 _ 占位
for _, item := range arr {
    fmt.Println(item)
}

函数

// 以下函数接收类型为 int32 的两个参数,并返回 3 个类型为 int32 的值
func add(a, b int32) (int32, int32, int32){
    return a, b, a + b
}

a, b, result := add(1, 2)

错误处理

// 没有问题:result, ok := test()
result, error := test()

if error != nil {
    // 处理错误
    return
}

指针

type A struct {
    b int32
}

func main(){
    a := 1
    example(&a)

    b := A{b: 1}
    example2(&b)
}

func example(a *int) {
    *a = 2
    fmt.Println(a)
}

func example2(a *A){
    (*a).b = 2
    fmt.Println("test:", a)
}

类方法

比如 ts 中定义一个 arr.push 之类的方法

class Array {
  private arr: number[];
  constructor(arr: number[]) {
    this.arr = arr;
  }

  push() {
    // ....
  }
}

在 go 语言中可以这样实现

type Array[T any] interface {
    push(args ...T) int
    forEach(callback func(item T, index int, array []T))
}

type ArraySt[T any] struct {
    array []T
}

// 结构体绑定方法要在外面写
// go 语言中不存在 this,是用接收器实现的
func (arrSt *ArraySt[T]) push (args ...T) int {
    arrSt.array = append(arrSt.array, args...)
    return len(arrSt.array)
}

func (arrSt *ArraySt[T]) forEach (args ...T){
    for index, item := range arrSt.array {
        callback(item, index, arrSt.array)
    }
}

func main(){
    var arr Array[int32] = &ArraySt[int32]{
        []int32{1, 2, 3}
    }

    len := arr.push(4, 5)
    fmt.Println(len)

    arr.forEach(func(item int32, index int, arr []int32) {
        fmt.Println(item, index, arr)
    })
}

map

type Test struct {
    a int
    b int
}

test := Test{
    a: 1,
    b: 2,
}

func main(){
    // ket type 是 any,value type 是 int32
    var m map[any]int32

    m = map[interface{}]interface{}{
        "a": 1,
        1: 2,
        test: 3
    }

    a := m["a"]
    b := m[1]
    c := m[test]

    fmt.Println(a)

    m["a"] = 100
}

其他 tips

“” → 字符串,’’ → 字符

开头大写的变量才能被包外访问

Gin 基础

假设有学生数据如下:

type Student struct {
    Id      int64       `json:"id"`
    Name    string      `json:"name"`
    Age     int32       `json:"age"`
    Courses []string    `json:"courses"`
}

Students := []Student{
    {
        Id: 1,
        Name: "Mike",
        Age: 15,
        Courses: []string{"Java", "JS"}
    }
}

可以编写后端代码形式如下:

package main

import (
    "github.com/gin-gonic/gin"
)

// 解决跨域问题

func Cors () gin.HandlerFunc {
    return func(c *gin.Context){
        c.Header("Access-Control-Allow-Origin", "*")
        c.Header("Access-Control-Allow-Headers", "Content-Type")
        c.Header("Access-Control-Allow-Methods", "GET,POST")

        if c.Request.Method == "OPTIONS" {
            c.JSON(http.StatusOK, "")
            c.Abort()
            return
        }

        c.Next()
    }
}

func main(){
    r := gin.Default()
    r.Use(Cors())

    r.GET("students", func (c *gin.Context){
        c.JSON(http.StatusOK, gin.H {
            "code": 0,
            "msg": "ok",
            "data": data.students
        })
    })

    r.GET("/student/:id", func(c *gin.Context){
        id, _ := strconv.ParseInt(c.Param("id"), 10, 64)

        for _, s := range data.Student {
            if s.Id === id {
                c.JSON(http.StatusOK, gin.H {
                    "code": 0,
                    "msg": "ok",
                    "data": s,
                })
            }
        }
    })

    r.POST("/delete", func (c *gin.Context){
        var body PostBody

        if err := c.ShouldBindJSON(&body); err != nil {
            c.JSON(400, gin.H{
                "code": 1,
                "msg": err.Error(),
            })
            return
        }

        for i, s := range data.Students {
            if s.Id == body.Id {
                target := data.Students[i]
                data.Students = append(data.Students[:i], data.Students[i + 1:]...)
                c.JSON(http.StatusOK, gin.H{
                    "code": 0,
                    "msg": "ok",
                    "data": target
                })

                return;
            }
        }

        c.JSON(http.StatusOK, gin.H{
            "code": 1,
            "msg": "Invalid student ID",
        })
    })

    r.POST("/edit", func (c *gin.Context){
        var body data.Student

        if err := c.ShouldBindJSON(&body); err != nil {
            c.JSON(400, gin.H{
                "code": 1,
                "msg": err.Error(),
            })
            return
        }

        for i, s := range data.Students {
            if s.Id == body.Id {
                data.Student[i] = body;
                c.JSON(http.StatusOK, gin.H{
                    "code": 0,
                    "msg": "ok",
                    "data": s.Id
                })

                return;
            }
        }

        c.JSON(http.StatusOK, gin.H{
            "code": 1,
            "msg": "Invalid student ID",
        })
    })

    if err := r.Run(":3000"); err != nil {
        fmt.Println("Server error")
    }
}

参考:https://www.bilibili.com/video/BV1EC411p7AK 一款更适合前端宝宝的 go 入门视频