--- title: "go语言基础学习一" --- # defer 的执行顺序# defer的执行顺序类似于栈,后进先出: defer若要修改return的返回数据,需要使用指针 不然return的返回值不会生被修改。 因为return会在defer执行前暂存要返回的数据 \`\`\`go // 错误修改示例 package main import ( "fmt" ) func test() int { i := 0 defer func() { fmt.Println("defer1") }() defer func() { i += 1 fmt.Println("defer2") }() return i } func main() { fmt.Println("return", test()) } //预期: //defer2 //defer1 //return 0 //正确修改示例1 func test() \*int { i := 0 j := \&i defer func() { fmt.Println("defer1") }() defer func() { \*j += 1 fmt.Println("defer2") }() return j } func main() { fmt.Println("return", \*test()) } //正确修改示例2: func test() (ret int) { ret = 0 defer func() { fmt.Println("defer1") }() defer func() { ret += 1 fmt.Println("defer2") }() return ret } func main() { fmt.Println("return", test()) } //预期: //defer2 //defer1 //return 1 \`\`\` # 如何交换 2 个变量的值?# \`\`\`go //对于变量类型: a, b = b,a //对于指针类型 \*a,\*b=\*b,\*a \`\`\` # Go 语言 tag 的用处?# tag可以为结构成员提供属性如: 1,json序列化 \`\`\`go import ( "encoding/json" "fmt" ) type User struct { Name string \`json:"name"\` Age int \`json:"age"\` Statue bool \`json:"-"\` } func main() { user := User{} user.Name = "张三" user.Age = 18 user.Statue = true data, _ := json.Marshal(user) fmt.Print(string(data)) } //预期: //{"name":"张三","age":18} \`\`\` 2,db: sqlx模块中对应的数据库字段名 \`\`\`go import ( "fmt" "github.com/jmoiron/sqlx" _ "github.com/go-sql-driver/mysql" ) // 数据库表 user 字段:id, user_name, age type User struct { ID int \`db:"id"\` // 结构体ID → 库字段 id Username string \`db:"user_name"\` // 结构体Username → 库字段 user_name Age int \`db:"age"\` } func main() { db, err := sqlx.Connect("mysql", "root:123456@tcp(127.0.0.1:3306)/testdb") if err != nil { panic(err) } defer db.Close() var u User // 自动按 db 标签映射结果到结构体 err = db.Get(\&u, "SELECT id,user_name,age FROM user WHERE id=1") if err != nil { panic(err) } fmt.Printf("%+v\\n", u) } \`\`\` 3、form: gin框架中对应的前端的数据字段名 \`\`\`go import ( "github.com/gin-gonic/gin" ) // 绑定 GET 查询参数 / POST 表单 type Req struct { Username string \`form:"username"\` // 前端传 username Age int \`form:"age"\` Page int \`form:"page"\` } func handler(c \*gin.Context) { var req Req // 自动绑定 form 数据到结构体 if err := c.ShouldBind(\&req); err != nil { c.JSON(400, gin.H{"msg": "参数错误"}) return } c.JSON(200, gin.H{"data": req}) } func main() { r := gin.Default() r.GET("/test", handler) r.POST("/test", handler) r.Run(":8080") } \`\`\` # 如何获取一个结构体的所有tag?# \`\`\`go import ( "fmt" "reflect" ) type Author struct { Name int \`json:Name\` Publications \[\]string \`json:Publication,omitempty\` } func main() { // 获取结构体类型信息 t := reflect.TypeOf(Author{}) // 遍历结构体的所有字段 for i := 0; i \< t.NumField(); i++ { // 获取字段名 name := t.Field(i).Name // 根据字段名获取字段信息 s, _ := t.FieldByName(name) // 打印字段名和字段标签 fmt.Println(name, s.Tag) } } //预期: //Name json:Name //Publications json:Publication,omitempty \`\`\` # 如何判断 2 个字符串切片(slice) 是相等的?# \`\`\`go package main import ( "fmt" "reflect" ) func main() { var s1 \[\]string // nil 切片 s2 := \[\]string{} // 空切片 s3 := \[\]string{"a", "b"} s4 := \[\]string{"a", "b"} s5 := \[\]string{"a", "c"} fmt.Println(reflect.DeepEqual(s1, s2)) // true fmt.Println(reflect.DeepEqual(s3, s4)) // true fmt.Println(reflect.DeepEqual(s3, s5)) // false } \`\`\`