当前位置: 首页 > news >正文

Golang: Store Query Result in a Map

目录

  • 1. Golang: Store Query Result in a Map
    • 1.1. Using Structs
    • 1.2. Using Maps

1. Golang: Store Query Result in a Map

注意: 使用这个可能会造成列名和列值乱串的现象,解决这个可以使用 AS 语法:

SELECT TENANT_ID AS TENANT_ID,SVR_IP AS SVR_IP,SVR_PORT AS SVR_PORT,PLAN_ID AS PLAN_ID,SQL_ID AS SQL_ID,TYPE AS TYPE,DB_ID AS DB_ID,STATEMENT AS STATEMENT,PLAN_HASH AS PLAN_HASH,LAST_ACTIVE_TIME AS LAST_ACTIVE_TIME,ELAPSED_TIME AS ELAPSED_TIME
FROM GV$PLAN_CACHE_PLAN_STAT
WHERE LAST_ACTIVE_TIME > '%s' AND LAST_ACTIVE_TIME <= '%s' AND ELAPSED_TIME > %d

Converting the results of a SQL query to a struct in Go is trivial, but sometimes you don’t know ahead of time exactly what columns and types you’re going to be retrieving, and a map may be better suited for storing the results.

1.1. Using Structs

First, here’s the standard way we can convert results to a struct:

rows, _ := db.Query("SELECT ...") // Note: Ignoring errors for brevity
for rows.Next() {s := myStruct{}if err := rows.Scan(&s); err != nil {return err}// Do something with 's'
}

Easy enough, but storing your query result in a map is a bit trickier.

1.2. Using Maps

Let’s say for example you’re working with a user’s database where you don’t know the schema ahead of time. You can’t write a struct to store the results, because you don’t know what columns and data types you’re going to be retrieving. What we want in this case is a map[string]interface{} where the key is the column name and the value could be any data type.

You might assume you can do the following:

rows, _ := db.Query("SELECT ...") // Note: Ignoring errors for brevity
for rows.Next() {m := make(map[string]interface{})// This WON'T WORKif err := rows.Scan(&m); err != nil {// ERROR: sql: expected X destination arguments in Scan, not 1}
}

Basically the SQL package is thinking that you expect a single column to be returned and for it to be a map[string]interface{} compatible type, which isn’t what we we’re trying to do.

Instead what we have to do in order to make this work is the following:

rows, _ := db.Query("SELECT ...") // Note: Ignoring errors for brevity
cols, _ := rows.Columns()for rows.Next() {// Create a slice of interface{}'s to represent each column,// and a second slice to contain pointers to each item in the columns slice.columns := make([]interface{}, len(cols))columnPointers := make([]interface{}, len(cols))for i, _ := range columns {columnPointers[i] = &columns[i]}// Scan the result into the column pointers...if err := rows.Scan(columnPointers...); err != nil {return err}// Create our map, and retrieve the value for each column from the pointers slice,// storing it in the map with the name of the column as the key.m := make(map[string]interface{})for i, colName := range cols {val := columnPointers[i].(*interface{})m[colName] = *val}// Outputs: map[columnName:value columnName2:value2 columnName3:value3 ...] fmt.Print(m)
}

So how does this work? Well first we query and get our rows as usual, but this time we use rows.Columns() to get a reference to all column names in the result.

Then for each row, we create a slice of interface{}’s called columns who’s length matches the number of columns. Next we create a second slice with the same length called columnPointers, but this time we iterate over each element in columns and store a pointer to the interface{} element in our columnPointers slice. This is necessary because the sql package requires pointers when scanning. So now we have two slices, one of interface{}s and one of pointers to the interface{}s.

Now we can scan the row into the slice of interface{} pointers (ie. columnPointers).

Finally, we create our map[string]interface{}, and iterate over the column names. For each column name (colName), we deference the interface{} pointer at the current loop index from the columnPointers slice, which references the value in the columns slice. We take this dereferenced value and store it in the map as the value, with the key being the column name.

Now we can use the map however we need, essentially allowing us to perform queries dynamically, without requiring knowledge of the schema we’re going to be querying when we write our code.

This may seem a little confusing at first, especially if you have no prior experience with pointers. If so, I’d recommend reading up on Pointers and trying the code out, inserting some debug logging to fully understand what’s happening during each step of the process.

相关文章:

  • Django学习日志07
  • ZYNQ_project:test_fifo_255X8
  • 基于JavaWeb+SpringBoot+Vue电子商城微信小程序系统的设计和实现
  • 第十章 : 如何使用MockMvc 快速编写Reslful API 测试用例
  • Mac 安装 protobuf 和Android Studio 使用
  • Linux(3):Linux 的文件权限与目录配置
  • 认识Modbus通信协议(笔记)
  • WPF MVVM模式介绍
  • 系统安全-常见的几种sql注入攻击的方式
  • SQL SERVER 2008安装教程
  • 学习raft协议(1)
  • os.path.join函数用法
  • gRPC 的原理 介绍带你从头了解gRPC
  • 【Qt之QWizardPage】使用
  • Ubuntu 20.04 LTS ffmpeg gif mp4 互转 许编译安装ffmpeg ;解决gif转mp4转换后无法播放问题
  • 《Java编程思想》读书笔记-对象导论
  • E-HPC支持多队列管理和自动伸缩
  • Facebook AccountKit 接入的坑点
  • JavaScript创建对象的四种方式
  • js操作时间(持续更新)
  • learning koa2.x
  • Vultr 教程目录
  • yii2权限控制rbac之rule详细讲解
  • 马上搞懂 GeoJSON
  • 微信小程序填坑清单
  • 为什么要用IPython/Jupyter?
  • 我与Jetbrains的这些年
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • 用jQuery怎么做到前后端分离
  • 再次简单明了总结flex布局,一看就懂...
  • 1.Ext JS 建立web开发工程
  • ​虚拟化系列介绍(十)
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • (1)Android开发优化---------UI优化
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (八十八)VFL语言初步 - 实现布局
  • (七)c52学习之旅-中断
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (转)jdk与jre的区别
  • (转)Linq学习笔记
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转)Sql Server 保留几位小数的两种做法
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .net core 依赖注入的基本用发
  • .NET Framework与.NET Framework SDK有什么不同?
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET开发不可不知、不可不用的辅助类(一)
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • .NET微信公众号开发-2.0创建自定义菜单
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • :=
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • [ vulhub漏洞复现篇 ] Apache APISIX 默认密钥漏洞 CVE-2020-13945
  • [ vulhub漏洞复现篇 ] Hadoop-yarn-RPC 未授权访问漏洞复现