Iris后台管理Demo

后台管理开发

1. 商品模型设计开发
2. 商品增删改查功能开发
3. 后台商品管理页面开发

结构体的Tag

  在golang中,命名都是推荐都是用驼峰方式,并且在首字母大小写有特殊的语法含义:包外无法引用。但是由经常需要和其它的系统进行数据交互,例如转成json格式,存储到Redis等等。这个时候如果直接用属性名来作为键值会不符合项目要求。

  • tag的作用: tag相当于该字段的一个属性标签, 在Go语言中, 一些包通过tag来做相应的判断
    type Student struct {
        Name string`json:"name"`
    }
    
    v, err := json.Marshal(s1) // json.Marshal方法,json序列化,返回值和报错信息
    if err != nil { // 不为nil代表报错
        fmt.Println(err)
    }
    fmt.Println(string(v))   // []byte转string, json  如果不进行转换json后的key为大写显得鸡肋
    

GO语言的ORM

ORM是数据库与程序之间的映射关系的实现,将数据库中的数据转换成程序的实现

  • models.go 为数据画出模子,数据库中的数据最后来填充它,使用tag标签,来区分结构体的不同属性。
    package datamodels
    
    type Product struct {
    	ID            int64  `json:"id" sql:"id" imooc:"id"` // 可以用来映射表字段
    	ProductName   string `json:"ProductName" sql:"productName" imooc:"ProductName"`
    	ProductNum    int64  `json:"ProductNum" sql:"productNum" imooc:"ProductNum"`
    	ProductImgage string `json:"ProductImage" sql:"productImage" imooc:"ProductImage"`
    	ProductUrl    string `json:"ProductUrl" sql:"productUrl" imooc:"ProductImage"`
    }
    
  • comm.go 为填充模子的工具,根据模子中各个属性,将从数据库中取得的数据填充
    package common
    
    import (
    	"errors"
    	"fmt"
    	"reflect"
    	"strconv"
    	"time"
    )
    
    //根据结构体中sql标签映射数据到结构体中并且转换类型
    func DataToStructByTagSql(data map[string]string, obj interface{}) {
    	objValue := reflect.ValueOf(obj).Elem()
    	for key, value := range data {
    		strKey := fmt.Sprintf("data的: %v", key)
    		strValue := fmt.Sprintf("data的val:%v", value)
    		data[strKey] = strValue
    	}
    
    	for i := 0; i < objValue.NumField(); i++ {
    		fmt.Println("i的值为:" + strconv.Itoa(i))
    		fmt.Println("obj 结构体对应的下标为:" + objValue.Type().Field(i).Tag.Get("sql"))
    
    		//获取sql对应的值
    		value := data[objValue.Type().Field(i).Tag.Get("sql")]
    
    		fmt.Println("当前下标回去的Map对应的value值为:" + value)
    		//获取对应字段的名称
    		name := objValue.Type().Field(i).Name
    		//获取对应字段类型
    		structFieldType := objValue.Field(i).Type()
    		//获取变量类型,也可以直接写"string类型"
    		val := reflect.ValueOf(value)
    		var err error
    		if structFieldType != val.Type() {
    			//类型转换
    			val, err = TypeConversion(value, structFieldType.Name()) //类型转换
    			if err != nil {
    
    			}
    		}
    		//设置类型值
    		objValue.FieldByName(name).Set(val)
    	}
    }
    
    //类型转换
    func TypeConversion(value string, ntype string) (reflect.Value, error) {
    	if ntype == "string" {
    		return reflect.ValueOf(value), nil
    	} else if ntype == "time.Time" {
    		t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
    		return reflect.ValueOf(t), err
    	} else if ntype == "Time" {
    		t, err := time.ParseInLocation("2006-01-02 15:04:05", value, time.Local)
    		return reflect.ValueOf(t), err
    	} else if ntype == "int" {
    		i, err := strconv.Atoi(value)
    		return reflect.ValueOf(i), err
    	} else if ntype == "int8" {
    		i, err := strconv.ParseInt(value, 10, 64)
    		return reflect.ValueOf(int8(i)), err
    	} else if ntype == "int32" {
    		i, err := strconv.ParseInt(value, 10, 64)
    		return reflect.ValueOf(int64(i)), err
    	} else if ntype == "int64" {
    		i, err := strconv.ParseInt(value, 10, 64)
    		return reflect.ValueOf(i), err
    	} else if ntype == "float32" {
    		i, err := strconv.ParseFloat(value, 64)
    		return reflect.ValueOf(float32(i)), err
    	} else if ntype == "float64" {
    		i, err := strconv.ParseFloat(value, 64)
    		return reflect.ValueOf(i), err
    	}
    
    	//else if .......增加其他一些类型的转换
    	return reflect.ValueOf(value), errors.New("未知的类型:" + ntype)
    }
    
  • test.go 模拟数据的转换
    package main
    
    import (
    	"test-produce/common"
    	"test-produce/datamodels"
    )
    
    func main() {
        // 模拟从数据库中取得的数据
    	data := map[string]string{"id":"1","productName":"imooc Test","productNum":"3","productImage":"/image1.jpg","productUrl":"www.baidu.com"}
    
    	product := &datamodels.Product{}
    	common.DataToStructByTagSql(data, product)
    }
    
    /*
     	运行结果:
    	 	i的值为:0
            obj 结构体对应的下标为:id
            当前下标回去的Map对应的value值为:1
            i的值为:1
            obj 结构体对应的下标为:productName
            当前下标回去的Map对应的value值为:imooc Test
            i的值为:2
            obj 结构体对应的下标为:productNum
            当前下标回去的Map对应的value值为:3
            i的值为:3
            obj 结构体对应的下标为:productImage
            当前下标回去的Map对应的value值为:/image1.jpg
            i的值为:4
            obj 结构体对应的下标为:productUrl
            当前下标回去的Map对应的value值为:www.baidu.com
    */
    

Go语言和Mysql交互

针对数据库中的数据,使用go语言进行增删改查

package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"log"
)

func main() {
	db, err := sql.Open("mysql", "root:123@tcp(127.0.0.1:3306)/imooc?charset=utf8")
	defer db.Close()
	
	// Query 和 Scan的简单使用
	rows, err := db.Query("SELECT productName FROM product WHERE id > ?", 0)
	if err != nil {
		log.Fatal(err)
	}

	// rows.Next() 类似于迭代器,返回每条记录, 返回多行数据
	for rows.Next() {
		var productName string
		// 通过Query得到的rows, 需要我们设置一个变量进行接受,通过rows.Scan(指针),将值传递给变量
		if err := rows.Scan(&productName); err != nil {
			log.Fatal(err)
		}
		fmt.Printf("多行数据: %s\n ", productName)
	}
	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}

	// QueryRaw 用于返回单行的查询, 如果是*的话,需要使用多个参数进行接受
	//rows1 := db.QueryRow("SELECT * FROM product WHERE id = ?", 1)
	rows1 := db.QueryRow("SELECT productNum FROM product WHERE id = ?", 1)
	var productNum int64
	if err := rows1.Scan(&productNum); err != nil {
		log.Fatal(err)
	}
	fmt.Printf("单行数据: %d\n", productNum)

	// 预占位符,db.Prepare()返回一个Stmt。Stmt对象可以执行Exec,Query,QueryRow等操作。
	stmt, _ := db.Prepare("insert into product (productName, productNum, productImage, productUrl) values (?,?,?,?)")

	// Exec() 执行函数,常用作执行增删该等操作
	row2, err := stmt.Exec(
		"娃哈哈",
		5,
		"/ha.jpg",
		"/ha",
	)
	idNew, errId := row2.LastInsertId()
	if errId != nil {
		fmt.Println(errId)
	}
	fmt.Printf("数据插入成功!返回操作的数据的ID: %d", idNew)
}

源码地址:https://github.com/wuyuz/goProduct

猜你喜欢

转载自www.cnblogs.com/double-W/p/12594817.html