如何从Mysql读取数据填充Golang的Struct类型map
Golang从MySQL读取数据填充map类型结构体字段方案
前置说明
MySQL是关系型数据库,无法直接存储Go的map结构,所以你需要先设计两张关联表分别存储流和对应频道的持久化信息。ChannelST中小写开头的非导出字段、通道、切片、map类型的运行时字段不需要存入数据库,查询时手动初始化即可。
表结构设计参考
-- 流信息表 CREATE TABLE `stream` ( `name` varchar(255) NOT NULL PRIMARY KEY COMMENT '流名称' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 频道信息表,和流表通过stream_name关联 CREATE TABLE `channel` ( `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, `stream_name` varchar(255) NOT NULL COMMENT '关联的流名称', `name` varchar(255) NOT NULL COMMENT '频道名称', `url` varchar(1024) NOT NULL COMMENT '频道地址', `on_demand` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否按需加载', `debug` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否开启调试', `status` int NOT NULL DEFAULT '0' COMMENT '频道状态', `ack` datetime NOT NULL COMMENT '确认时间', INDEX `idx_stream_name`(`stream_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
代码实现(以GORM为例)
第一步:定义数据库映射模型
仅包含需要持久化到MySQL的字段即可:
import "time" // DBStream 对应stream表 type DBStream struct { Name string `gorm:"column:name;primaryKey"` } // DBChannel 对应channel表 type DBChannel struct { StreamName string `gorm:"column:stream_name"` Name string `gorm:"column:name"` URL string `gorm:"column:url"` OnDemand bool `gorm:"column:on_demand"` Debug bool `gorm:"column:debug"` Status int `gorm:"column:status"` Ack time.Time `gorm:"column:ack"` }
第二步:查询并组装目标结构体
func GetStreamWithChannels(streamName string) (*StreamST, error) { // 1. 查询流基础信息 var dbStream DBStream if err := db.Model(&DBStream{}).Where("name = ?", streamName).First(&dbStream).Error; err != nil { return nil, err } // 2. 查询该流关联的所有频道 var dbChannels []DBChannel if err := db.Model(&DBChannel{}).Where("stream_name = ?", streamName).Find(&dbChannels).Error; err != nil { return nil, err } // 3. 组装成StreamST结构,填充Channels map stream := &StreamST{ Name: dbStream.Name, Channels: make(map[string]ChannelST, len(dbChannels)), } for _, dbChan := range dbChannels { chanItem := ChannelST{ Name: dbChan.Name, URL: dbChan.URL, OnDemand: dbChan.OnDemand, Debug: dbChan.Debug, Status: dbChan.Status, Ack: dbChan.Ack, // 运行时字段手动初始化 runLock: false, codecs: make([]av.CodecData, 0), sdp: make([]byte, 0), signals: make(chan int, 1), hlsSegmentBuffer: make(map[int]SegmentOld), hlsSegmentNumber: 0, clients: make(map[string]ClientST), } // 以频道名为key存入map stream.Channels[chanItem.Name] = chanItem } return stream, nil }
注意事项
- 如果使用原生
database/sql库,逻辑完全一致,只是把GORM的查询替换为原生SQL查询、Scan赋值即可。 - 如果需要批量查询所有流的信息,可先查全量流数据,再查全量频道数据按
stream_name分组,逐个组装对应流的Channels map即可。 - 运行时字段不要存入MySQL,这类动态结构、锁、通道类型本身也不支持序列化存储到关系型数据库。
内容的提问来源于stack exchange,提问作者ziyu
相关产品推荐
相关产品推荐

